dedot 0.0.1-alpha.22

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 (100) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +245 -0
  3. package/cjs/client/Dedot.js +444 -0
  4. package/cjs/client/index.js +17 -0
  5. package/cjs/executor/ConstantExecutor.js +22 -0
  6. package/cjs/executor/ErrorExecutor.js +47 -0
  7. package/cjs/executor/EventExecutor.js +53 -0
  8. package/cjs/executor/Executor.js +39 -0
  9. package/cjs/executor/RpcExecutor.js +109 -0
  10. package/cjs/executor/RuntimeApiExecutor.js +93 -0
  11. package/cjs/executor/StorageQueryExecutor.js +33 -0
  12. package/cjs/executor/TxExecutor.js +153 -0
  13. package/cjs/executor/index.js +24 -0
  14. package/cjs/extrinsic/SubmittableResult.js +33 -0
  15. package/cjs/extrinsic/extensions/ExtraSignedExtension.js +65 -0
  16. package/cjs/extrinsic/extensions/SignedExtension.js +41 -0
  17. package/cjs/extrinsic/extensions/index.js +19 -0
  18. package/cjs/extrinsic/extensions/known/ChargeAssetTxPayment.js +44 -0
  19. package/cjs/extrinsic/extensions/known/ChargeTransactionPayment.js +16 -0
  20. package/cjs/extrinsic/extensions/known/CheckGenesis.js +19 -0
  21. package/cjs/extrinsic/extensions/known/CheckMortality.js +71 -0
  22. package/cjs/extrinsic/extensions/known/CheckNonZeroSender.js +10 -0
  23. package/cjs/extrinsic/extensions/known/CheckNonce.js +34 -0
  24. package/cjs/extrinsic/extensions/known/CheckSpecVersion.js +19 -0
  25. package/cjs/extrinsic/extensions/known/CheckTxVersion.js +19 -0
  26. package/cjs/extrinsic/extensions/known/CheckWeight.js +10 -0
  27. package/cjs/extrinsic/extensions/known/PrevalidateAttests.js +11 -0
  28. package/cjs/extrinsic/extensions/known/index.js +25 -0
  29. package/cjs/extrinsic/index.js +18 -0
  30. package/cjs/index.js +25 -0
  31. package/cjs/package.json +1 -0
  32. package/cjs/packageInfo.js +5 -0
  33. package/cjs/proxychain.js +20 -0
  34. package/cjs/storage/QueryableStorage.js +99 -0
  35. package/cjs/types.js +2 -0
  36. package/client/Dedot.d.ts +181 -0
  37. package/client/Dedot.js +440 -0
  38. package/client/index.d.ts +1 -0
  39. package/client/index.js +1 -0
  40. package/executor/ConstantExecutor.d.ts +11 -0
  41. package/executor/ConstantExecutor.js +18 -0
  42. package/executor/ErrorExecutor.d.ts +11 -0
  43. package/executor/ErrorExecutor.js +43 -0
  44. package/executor/EventExecutor.d.ts +11 -0
  45. package/executor/EventExecutor.js +49 -0
  46. package/executor/Executor.d.ts +150 -0
  47. package/executor/Executor.js +35 -0
  48. package/executor/RpcExecutor.d.ts +14 -0
  49. package/executor/RpcExecutor.js +105 -0
  50. package/executor/RuntimeApiExecutor.d.ts +9 -0
  51. package/executor/RuntimeApiExecutor.js +89 -0
  52. package/executor/StorageQueryExecutor.d.ts +10 -0
  53. package/executor/StorageQueryExecutor.js +29 -0
  54. package/executor/TxExecutor.d.ts +47 -0
  55. package/executor/TxExecutor.js +147 -0
  56. package/executor/index.d.ts +8 -0
  57. package/executor/index.js +8 -0
  58. package/extrinsic/SubmittableResult.d.ts +19 -0
  59. package/extrinsic/SubmittableResult.js +29 -0
  60. package/extrinsic/extensions/ExtraSignedExtension.d.ts +14 -0
  61. package/extrinsic/extensions/ExtraSignedExtension.js +61 -0
  62. package/extrinsic/extensions/SignedExtension.d.ts +40 -0
  63. package/extrinsic/extensions/SignedExtension.js +37 -0
  64. package/extrinsic/extensions/index.d.ts +3 -0
  65. package/extrinsic/extensions/index.js +3 -0
  66. package/extrinsic/extensions/known/ChargeAssetTxPayment.d.ts +14 -0
  67. package/extrinsic/extensions/known/ChargeAssetTxPayment.js +40 -0
  68. package/extrinsic/extensions/known/ChargeTransactionPayment.d.ts +6 -0
  69. package/extrinsic/extensions/known/ChargeTransactionPayment.js +12 -0
  70. package/extrinsic/extensions/known/CheckGenesis.d.ts +10 -0
  71. package/extrinsic/extensions/known/CheckGenesis.js +15 -0
  72. package/extrinsic/extensions/known/CheckMortality.d.ts +15 -0
  73. package/extrinsic/extensions/known/CheckMortality.js +67 -0
  74. package/extrinsic/extensions/known/CheckNonZeroSender.d.ts +6 -0
  75. package/extrinsic/extensions/known/CheckNonZeroSender.js +6 -0
  76. package/extrinsic/extensions/known/CheckNonce.d.ts +10 -0
  77. package/extrinsic/extensions/known/CheckNonce.js +30 -0
  78. package/extrinsic/extensions/known/CheckSpecVersion.d.ts +9 -0
  79. package/extrinsic/extensions/known/CheckSpecVersion.js +15 -0
  80. package/extrinsic/extensions/known/CheckTxVersion.d.ts +9 -0
  81. package/extrinsic/extensions/known/CheckTxVersion.js +15 -0
  82. package/extrinsic/extensions/known/CheckWeight.d.ts +6 -0
  83. package/extrinsic/extensions/known/CheckWeight.js +6 -0
  84. package/extrinsic/extensions/known/PrevalidateAttests.d.ts +7 -0
  85. package/extrinsic/extensions/known/PrevalidateAttests.js +7 -0
  86. package/extrinsic/extensions/known/index.d.ts +3 -0
  87. package/extrinsic/extensions/known/index.js +22 -0
  88. package/extrinsic/index.d.ts +2 -0
  89. package/extrinsic/index.js +2 -0
  90. package/index.d.ts +6 -0
  91. package/index.js +5 -0
  92. package/package.json +54 -0
  93. package/packageInfo.d.ts +4 -0
  94. package/packageInfo.js +3 -0
  95. package/proxychain.d.ts +7 -0
  96. package/proxychain.js +16 -0
  97. package/storage/QueryableStorage.d.ts +16 -0
  98. package/storage/QueryableStorage.js +95 -0
  99. package/types.d.ts +44 -0
  100. package/types.js +1 -0
@@ -0,0 +1,150 @@
1
+ import type { SubstrateApi } from '@dedot/chaintypes';
2
+ import { BlockHash, PalletDefLatest } from '@dedot/codecs';
3
+ import { GenericSubstrateApi } from '@dedot/types';
4
+ import { Dedot } from '../client';
5
+ /**
6
+ * @name Executor
7
+ * @description Execution abstraction for a specific action
8
+ */
9
+ export declare abstract class Executor<ChainApi extends GenericSubstrateApi = SubstrateApi> {
10
+ #private;
11
+ constructor(api: Dedot<ChainApi>, atBlockHash?: BlockHash);
12
+ get api(): Dedot<ChainApi>;
13
+ get atBlockHash(): `0x${string}` | undefined;
14
+ get provider(): import("@polkadot/rpc-provider/types").ProviderInterface;
15
+ get registry(): import("@dedot/codecs").CodecRegistry;
16
+ get metadata(): {
17
+ types: {
18
+ id: number;
19
+ path: string[];
20
+ params: {
21
+ name: string;
22
+ typeId: number | undefined;
23
+ }[];
24
+ type: {
25
+ tag: "Struct";
26
+ value: {
27
+ fields: import("@dedot/codecs").Field[];
28
+ };
29
+ } | {
30
+ tag: "Enum";
31
+ value: {
32
+ members: {
33
+ name: string;
34
+ fields: import("@dedot/codecs").Field[];
35
+ index: number;
36
+ docs: string[];
37
+ }[];
38
+ };
39
+ } | {
40
+ tag: "Sequence";
41
+ value: {
42
+ typeParam: number;
43
+ };
44
+ } | {
45
+ tag: "SizedVec";
46
+ value: {
47
+ len: number;
48
+ typeParam: number;
49
+ };
50
+ } | {
51
+ tag: "Tuple";
52
+ value: {
53
+ fields: number[];
54
+ };
55
+ } | {
56
+ tag: "Primitive";
57
+ value: {
58
+ kind: "bool" | "char" | "str" | "u8" | "u16" | "u32" | "u64" | "u128" | "u256" | "i8" | "i16" | "i32" | "i64" | "i128" | "i256";
59
+ };
60
+ } | {
61
+ tag: "Compact";
62
+ value: {
63
+ typeParam: number;
64
+ };
65
+ } | {
66
+ tag: "BitSequence";
67
+ value: {
68
+ bitOrderType: number;
69
+ bitStoreType: number;
70
+ };
71
+ };
72
+ docs: string[];
73
+ }[];
74
+ pallets: {
75
+ name: string;
76
+ storage: {
77
+ prefix: string;
78
+ entries: {
79
+ name: string;
80
+ modifier: string;
81
+ type: {
82
+ tag: "Plain";
83
+ value: {
84
+ valueTypeId: number;
85
+ };
86
+ } | {
87
+ tag: "Map";
88
+ value: {
89
+ hashers: ("identity" | "blake2_128" | "blake2_256" | "blake2_128Concat" | "twox128" | "twox256" | "twox64Concat")[];
90
+ keyTypeId: number;
91
+ valueTypeId: number;
92
+ };
93
+ };
94
+ default: `0x${string}`;
95
+ docs: string[];
96
+ }[];
97
+ } | undefined;
98
+ calls: number | undefined;
99
+ event: number | undefined;
100
+ constants: {
101
+ name: string;
102
+ typeId: number;
103
+ value: `0x${string}`;
104
+ docs: string[];
105
+ }[];
106
+ error: number | undefined;
107
+ index: number;
108
+ docs: string[];
109
+ }[];
110
+ extrinsic: {
111
+ version: number;
112
+ addressTypeId: number;
113
+ callTypeId: number;
114
+ signatureTypeId: number;
115
+ extraTypeId: number;
116
+ signedExtensions: {
117
+ ident: string;
118
+ typeId: number;
119
+ additionalSigned: number;
120
+ }[];
121
+ };
122
+ runtimeType: number;
123
+ apis: {
124
+ name: string;
125
+ methods: {
126
+ name: string;
127
+ inputs: {
128
+ name: string;
129
+ typeId: number;
130
+ }[];
131
+ output: number;
132
+ docs: string[];
133
+ }[];
134
+ docs: string[];
135
+ }[];
136
+ outerEnums: {
137
+ callEnumTypeId: number;
138
+ eventEnumTypeId: number;
139
+ errorEnumTypeId: number;
140
+ };
141
+ custom: {
142
+ map: ReadonlyMap<string, {
143
+ typeId: number;
144
+ value: `0x${string}`;
145
+ }>;
146
+ };
147
+ };
148
+ getPallet(name: string, throwErr?: boolean): PalletDefLatest;
149
+ abstract execute(...paths: string[]): unknown;
150
+ }
@@ -0,0 +1,35 @@
1
+ import { stringCamelCase } from '@polkadot/util';
2
+ /**
3
+ * @name Executor
4
+ * @description Execution abstraction for a specific action
5
+ */
6
+ export class Executor {
7
+ #api;
8
+ #atBlockHash;
9
+ constructor(api, atBlockHash) {
10
+ this.#api = api;
11
+ this.#atBlockHash = atBlockHash;
12
+ }
13
+ get api() {
14
+ return this.#api;
15
+ }
16
+ get atBlockHash() {
17
+ return this.#atBlockHash;
18
+ }
19
+ get provider() {
20
+ return this.api.provider;
21
+ }
22
+ get registry() {
23
+ return this.api.registry;
24
+ }
25
+ get metadata() {
26
+ return this.api.metadataLatest;
27
+ }
28
+ getPallet(name, throwErr = true) {
29
+ const targetPallet = this.metadata.pallets.find((p) => stringCamelCase(p.name) === name);
30
+ if (!targetPallet && throwErr) {
31
+ throw new Error(`Pallet not found: ${name}`);
32
+ }
33
+ return targetPallet;
34
+ }
35
+ }
@@ -0,0 +1,14 @@
1
+ import type { SubstrateApi } from '@dedot/chaintypes';
2
+ import { GenericSubstrateApi, RpcCallSpec, RpcParamSpec, GenericRpcCall } from '@dedot/types';
3
+ import { Executor } from './Executor';
4
+ /**
5
+ * @name RpcExecutor
6
+ * @description Execute a rpc based from an RPC spec,
7
+ * if a spec is not found we execute an arbitrary rpc method
8
+ */
9
+ export declare class RpcExecutor<ChainApi extends GenericSubstrateApi = SubstrateApi> extends Executor<ChainApi> {
10
+ execute(section: string, method: string): GenericRpcCall;
11
+ tryDecode(callSpec: RpcCallSpec, raw: any): any;
12
+ tryEncode(paramSpec: RpcParamSpec, value: any): any;
13
+ checkRpcInputs(callSpec: RpcCallSpec, actualArgs: any[]): void;
14
+ }
@@ -0,0 +1,105 @@
1
+ import { isFunction, u8aToHex } from '@polkadot/util';
2
+ import { findAliasRpcSpec, findRpcSpec } from '@dedot/specs';
3
+ import { assert, isNativeType } from '@dedot/utils';
4
+ import { Executor } from './Executor';
5
+ const isOptionalParam = (param) => {
6
+ return param.isOptional || param.name.startsWith('Option<');
7
+ };
8
+ /**
9
+ * @name RpcExecutor
10
+ * @description Execute a rpc based from an RPC spec,
11
+ * if a spec is not found we execute an arbitrary rpc method
12
+ */
13
+ export class RpcExecutor extends Executor {
14
+ execute(section, method) {
15
+ const maybeRpcName = `${section}_${method}`;
16
+ const callSpec = findRpcSpec(maybeRpcName) || findAliasRpcSpec(maybeRpcName);
17
+ const rpcName = callSpec?.name || `${section}_${method}`;
18
+ const isSubscription = !!callSpec?.pubsub;
19
+ const fnRpc = async (...args) => {
20
+ assert(callSpec, 'Rpc spec not found');
21
+ this.checkRpcInputs(callSpec, args);
22
+ const { params } = callSpec;
23
+ const formattedInputs = args.map((input, index) => this.tryEncode(params[index], input));
24
+ const result = await this.provider.send(rpcName, formattedInputs);
25
+ return this.tryDecode(callSpec, result);
26
+ };
27
+ const fnSubRpc = async (...args) => {
28
+ assert(callSpec, 'Rpc spec not found');
29
+ const inArgs = args.slice();
30
+ const callback = inArgs.pop();
31
+ assert(isFunction(callback), 'A callback is required for subscription');
32
+ this.checkRpcInputs(callSpec, inArgs);
33
+ const onNewMessage = (error, result) => {
34
+ if (error) {
35
+ console.error(error);
36
+ return;
37
+ }
38
+ callback(this.tryDecode(callSpec, result));
39
+ };
40
+ const { params, pubsub } = callSpec;
41
+ const formattedInputs = inArgs.map((input, index) => this.tryEncode(params[index], input));
42
+ const [subname, subscribe, unsubcribe] = pubsub;
43
+ const subscription = this.provider.subscribe(subname, subscribe, formattedInputs, onNewMessage);
44
+ return async () => {
45
+ return subscription
46
+ .then((subscriptionId) => this.provider.unsubscribe(subname, unsubcribe, subscriptionId))
47
+ .catch((err) => {
48
+ console.error(err);
49
+ return false;
50
+ });
51
+ };
52
+ };
53
+ if (!callSpec) {
54
+ // Call arbitrary rpc method
55
+ return async (...args) => {
56
+ return await this.provider.send(rpcName, args);
57
+ };
58
+ }
59
+ const oneFnRpc = isSubscription ? fnSubRpc : fnRpc;
60
+ oneFnRpc.meta = callSpec;
61
+ return oneFnRpc;
62
+ }
63
+ tryDecode(callSpec, raw) {
64
+ if (raw === null) {
65
+ // We use `undefined` to represent Option::None in the client
66
+ return undefined;
67
+ }
68
+ const { type, isScale } = callSpec;
69
+ if (isScale) {
70
+ return this.registry.findCodec(type).tryDecode(raw);
71
+ }
72
+ if (isNativeType(type)) {
73
+ return raw;
74
+ }
75
+ return raw;
76
+ }
77
+ tryEncode(paramSpec, value) {
78
+ const { type, isScale, isOptional } = paramSpec;
79
+ if (isScale) {
80
+ if (isOptional && (value === undefined || value === null)) {
81
+ return null;
82
+ }
83
+ const $codec = this.registry.findCodec(type);
84
+ return u8aToHex($codec.tryEncode(value));
85
+ }
86
+ // TODO generalize this!
87
+ if (value && value['toJSON']) {
88
+ return value.toJSON();
89
+ }
90
+ return value;
91
+ }
92
+ checkRpcInputs(callSpec, actualArgs) {
93
+ const params = callSpec.params;
94
+ if (params.length === actualArgs.length) {
95
+ return;
96
+ }
97
+ params.forEach((param, idx) => {
98
+ const isRequiredParam = !isOptionalParam(param);
99
+ if (isRequiredParam && actualArgs[idx] === undefined) {
100
+ const requiredParamCount = params.filter((p) => !isOptionalParam(p)).length;
101
+ throw new Error(`Miss match RPC params, required ${requiredParamCount} params, current inputs length: ${actualArgs.length}`);
102
+ }
103
+ });
104
+ }
105
+ }
@@ -0,0 +1,9 @@
1
+ import { Executor } from './Executor';
2
+ import { GenericRuntimeApiMethod, GenericSubstrateApi, RuntimeApiMethodParamSpec, RuntimeApiMethodSpec } from '@dedot/types';
3
+ export declare const FallbackRuntimeApis: (string | number)[][];
4
+ export declare class RuntimeApiExecutor<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends Executor<ChainApi> {
5
+ #private;
6
+ execute(runtimeApi: string, method: string): GenericRuntimeApiMethod;
7
+ tryDecode(callSpec: RuntimeApiMethodSpec, raw: any): unknown;
8
+ tryEncode(paramSpec: RuntimeApiMethodParamSpec, value: any): Uint8Array;
9
+ }
@@ -0,0 +1,89 @@
1
+ import { Executor } from './Executor';
2
+ import { assert, calculateRuntimeApiHash, stringSnakeCase } from '@dedot/utils';
3
+ import { isNumber, stringPascalCase, u8aConcat, u8aToHex } from '@polkadot/util';
4
+ import { findRuntimeApiMethodSpec } from '@dedot/specs';
5
+ export const FallbackRuntimeApis = [
6
+ ['0x37e397fc7c91f5e4', 2], // Metadata Api v2
7
+ ];
8
+ export class RuntimeApiExecutor extends Executor {
9
+ execute(runtimeApi, method) {
10
+ runtimeApi = stringPascalCase(runtimeApi);
11
+ method = stringSnakeCase(method);
12
+ const callName = `${runtimeApi}_${method}`;
13
+ const callSpec = this.#findRuntimeApiMethodSpec(runtimeApi, method);
14
+ assert(callSpec, `Runtime Api not found: ${callName}`);
15
+ const callFn = async (...args) => {
16
+ const { params } = callSpec;
17
+ const formattedInputs = params.map((param, index) => this.tryEncode(param, args[index]));
18
+ const bytes = u8aToHex(u8aConcat(...formattedInputs));
19
+ const callArgs = [callName, bytes];
20
+ if (this.atBlockHash) {
21
+ callArgs.push(this.atBlockHash);
22
+ }
23
+ const result = await this.api.rpc.state.call(...callArgs);
24
+ return this.tryDecode(callSpec, result);
25
+ };
26
+ callFn.meta = callSpec;
27
+ return callFn;
28
+ }
29
+ tryDecode(callSpec, raw) {
30
+ const { type, typeId } = callSpec;
31
+ if (isNumber(typeId)) {
32
+ return this.registry.findPortableCodec(typeId).tryDecode(raw);
33
+ }
34
+ return this.registry.findCodec(type).tryDecode(raw);
35
+ }
36
+ tryEncode(paramSpec, value) {
37
+ const { type, typeId } = paramSpec;
38
+ const $codec = isNumber(typeId) ? this.registry.findPortableCodec(typeId) : this.registry.findCodec(type);
39
+ return $codec.tryEncode(value);
40
+ }
41
+ #findRuntimeApiMethodSpec(runtimeApi, method) {
42
+ const methodDef = this.#findRuntimeApiMethodDef(runtimeApi, method);
43
+ if (methodDef) {
44
+ return this.#toMethodSpec(runtimeApi, methodDef);
45
+ }
46
+ return this.#findRuntimeApiMethodExternalSpec(runtimeApi, method);
47
+ }
48
+ #findRuntimeApiMethodDef(runtimeApi, method) {
49
+ try {
50
+ for (const api of this.metadata.apis) {
51
+ if (api.name !== runtimeApi)
52
+ continue;
53
+ for (const apiMethod of api.methods) {
54
+ if (apiMethod.name === method)
55
+ return apiMethod;
56
+ }
57
+ }
58
+ }
59
+ catch { }
60
+ }
61
+ #toMethodSpec(runtimeApi, methodDef) {
62
+ if (!methodDef)
63
+ return undefined;
64
+ const { name, inputs, output, docs } = methodDef;
65
+ return {
66
+ docs,
67
+ runtimeApiName: runtimeApi,
68
+ methodName: name,
69
+ type: '', // TODO generate type name
70
+ typeId: output,
71
+ params: inputs.map(({ name, typeId }) => ({
72
+ name,
73
+ type: '', // TODO generate type name
74
+ typeId,
75
+ })),
76
+ };
77
+ }
78
+ #findRuntimeApiMethodExternalSpec(runtimeApi, method) {
79
+ const targetRuntimeApiHash = calculateRuntimeApiHash(runtimeApi);
80
+ const runtimeApiVersions = this.api.runtimeVersion?.apis || FallbackRuntimeApis;
81
+ const targetRuntimeApiVersion = runtimeApiVersions
82
+ .find(([supportedRuntimeApiHash]) => targetRuntimeApiHash === supportedRuntimeApiHash)
83
+ ?.at(1);
84
+ if (!isNumber(targetRuntimeApiVersion)) {
85
+ return undefined;
86
+ }
87
+ return findRuntimeApiMethodSpec(`${runtimeApi}_${method}`, targetRuntimeApiVersion);
88
+ }
89
+ }
@@ -0,0 +1,10 @@
1
+ import type { SubstrateApi } from '@dedot/chaintypes';
2
+ import { GenericSubstrateApi } from '@dedot/types';
3
+ import { Executor } from './Executor';
4
+ /**
5
+ * @name StorageQueryExecutor
6
+ * @description Execute a query to on-chain storage
7
+ */
8
+ export declare class StorageQueryExecutor<ChainApi extends GenericSubstrateApi = SubstrateApi> extends Executor<ChainApi> {
9
+ execute(pallet: string, storage: string): (...args: any[]) => Promise<any>;
10
+ }
@@ -0,0 +1,29 @@
1
+ import { Executor } from './Executor';
2
+ import { QueryableStorage } from '../storage/QueryableStorage';
3
+ import { isFunction } from '@polkadot/util';
4
+ /**
5
+ * @name StorageQueryExecutor
6
+ * @description Execute a query to on-chain storage
7
+ */
8
+ export class StorageQueryExecutor extends Executor {
9
+ execute(pallet, storage) {
10
+ return async (...args) => {
11
+ const entry = new QueryableStorage(this.registry, pallet, storage);
12
+ const inArgs = args.slice();
13
+ const lastArg = args.at(-1);
14
+ const callback = isFunction(lastArg) ? inArgs.pop() : undefined;
15
+ const encodedKey = entry.encodeKey(inArgs.at(0));
16
+ // if a callback is passed, make a storage subscription and return an unsub function
17
+ if (callback) {
18
+ return await this.api.rpc.state.subscribeStorage([encodedKey], (changeSet) => {
19
+ const targetChange = changeSet.changes.find((change) => change[0] === encodedKey);
20
+ targetChange && callback(entry.decodeValue(targetChange[1]));
21
+ });
22
+ }
23
+ else {
24
+ const result = await this.api.rpc.state.getStorage(encodedKey, this.atBlockHash);
25
+ return entry.decodeValue(result);
26
+ }
27
+ };
28
+ }
29
+ }
@@ -0,0 +1,47 @@
1
+ import { Executor } from './Executor';
2
+ import { AddressOrPair, Callback, DryRunResult, GenericSubstrateApi, GenericTxCall, IRuntimeTxCall, ISubmittableResult, SignerOptions, Unsub } from '@dedot/types';
3
+ import { SubstrateApi } from '@dedot/chaintypes';
4
+ import { HexString } from '@dedot/utils';
5
+ import { BlockHash, Hash } from '@dedot/codecs';
6
+ import { IKeyringPair } from '@polkadot/types/types';
7
+ import { SignOptions } from '@polkadot/keyring/types';
8
+ export declare function isKeyringPair(account: AddressOrPair): account is IKeyringPair;
9
+ /**
10
+ * Sign a raw message
11
+ * @param signerPair
12
+ * @param raw
13
+ * @param options
14
+ */
15
+ export declare function signRaw(signerPair: IKeyringPair, raw: HexString, options?: SignOptions): Uint8Array;
16
+ /**
17
+ * @name TxExecutor
18
+ * @description Execute a transaction instruction, returns a submittable extrinsic
19
+ */
20
+ export declare class TxExecutor<ChainApi extends GenericSubstrateApi = SubstrateApi> extends Executor<ChainApi> {
21
+ execute(pallet: string, functionName: string): GenericTxCall;
22
+ createExtrinsic(call: IRuntimeTxCall): {
23
+ sign(fromAccount: AddressOrPair, options?: Partial<SignerOptions>): Promise<any>;
24
+ signAndSend(account: AddressOrPair, options?: Partial<SignerOptions>): Promise<Hash>;
25
+ signAndSend(account: AddressOrPair, callback: Callback<ISubmittableResult>): Promise<Unsub>;
26
+ signAndSend(account: AddressOrPair, options: Partial<SignerOptions>, callback?: Callback<ISubmittableResult>): Promise<Unsub>;
27
+ "__#51@#normalizeOptions"(partialOptions?: Partial<SignerOptions> | Callback<ISubmittableResult>, callback?: Callback<ISubmittableResult>): [Partial<SignerOptions>, Callback<ISubmittableResult> | undefined];
28
+ dryRun(account: AddressOrPair, optionsOrHash?: Partial<SignerOptions> | BlockHash): Promise<DryRunResult>;
29
+ send(): Promise<Hash>;
30
+ send(callback: Callback<ISubmittableResult>): Promise<Unsub>;
31
+ "__#10@#private": any;
32
+ registry: import("@dedot/codecs").CodecRegistry;
33
+ readonly signed: boolean;
34
+ readonly version: number;
35
+ readonly signature: import("@dedot/codecs").ExtrinsicSignatureV4<any, any, any> | undefined;
36
+ readonly call: any;
37
+ readonly callU8a: Uint8Array;
38
+ readonly callHex: `0x${string}`;
39
+ readonly callLength: number;
40
+ attachSignature(signature: import("@dedot/codecs").ExtrinsicSignatureV4<any, any, any>): void;
41
+ readonly $Codec: import("subshape").Shape<unknown, unknown>;
42
+ toU8a(): Uint8Array;
43
+ toHex(): `0x${string}`;
44
+ readonly length: number;
45
+ readonly hash: `0x${string}`;
46
+ };
47
+ }
@@ -0,0 +1,147 @@
1
+ import { Executor } from './Executor';
2
+ import { assert } from '@dedot/utils';
3
+ import { hexToU8a, isFunction, isHex, objectSpread, stringCamelCase, stringPascalCase, u8aToHex } from '@polkadot/util';
4
+ import { Extrinsic } from '@dedot/codecs';
5
+ import { ExtraSignedExtension, SubmittableResult } from '../extrinsic';
6
+ import { blake2AsHex, blake2AsU8a } from '@polkadot/util-crypto';
7
+ export function isKeyringPair(account) {
8
+ return isFunction(account.sign);
9
+ }
10
+ /**
11
+ * Sign a raw message
12
+ * @param signerPair
13
+ * @param raw
14
+ * @param options
15
+ */
16
+ export function signRaw(signerPair, raw, options) {
17
+ const u8a = hexToU8a(raw);
18
+ // Ref: https://github.com/paritytech/polkadot-sdk/blob/943697fa693a4da6ef481ef93df522accb7d0583/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs#L234-L238
19
+ const toSignRaw = u8a.length > 256 ? blake2AsU8a(u8a, 256) : u8a;
20
+ return signerPair.sign(toSignRaw, options);
21
+ }
22
+ /**
23
+ * @name TxExecutor
24
+ * @description Execute a transaction instruction, returns a submittable extrinsic
25
+ */
26
+ export class TxExecutor extends Executor {
27
+ execute(pallet, functionName) {
28
+ const targetPallet = this.getPallet(pallet);
29
+ assert(targetPallet.calls, 'Tx call type not found');
30
+ const txType = this.metadata.types[targetPallet.calls];
31
+ assert(txType.type.tag === 'Enum', 'Tx type should be enum');
32
+ const isFlatEnum = txType.type.value.members.every((m) => m.fields.length === 0);
33
+ const txCallDef = txType.type.value.members.find((m) => stringCamelCase(m.name) === functionName);
34
+ assert(txCallDef, 'Tx call not found');
35
+ const txCallFn = (...args) => {
36
+ let call;
37
+ if (isFlatEnum) {
38
+ call = {
39
+ pallet: stringPascalCase(targetPallet.name),
40
+ palletCall: stringPascalCase(txCallDef.name),
41
+ };
42
+ }
43
+ else {
44
+ const callParams = txCallDef.fields.reduce((o, { name }, idx) => {
45
+ o[stringCamelCase(name)] = args[idx];
46
+ return o;
47
+ }, {});
48
+ call = {
49
+ pallet: stringPascalCase(targetPallet.name),
50
+ palletCall: {
51
+ name: stringPascalCase(txCallDef.name),
52
+ params: callParams,
53
+ },
54
+ };
55
+ }
56
+ return this.createExtrinsic(call);
57
+ };
58
+ txCallFn.meta = {
59
+ ...txCallDef,
60
+ fieldCodecs: txCallDef.fields.map(({ typeId }) => this.registry.findPortableCodec(typeId)),
61
+ pallet: targetPallet.name,
62
+ palletIndex: targetPallet.index,
63
+ };
64
+ return txCallFn;
65
+ }
66
+ createExtrinsic(call) {
67
+ const api = this.api;
68
+ class SubmittableExtrinsic extends Extrinsic {
69
+ async sign(fromAccount, options) {
70
+ const address = isKeyringPair(fromAccount) ? fromAccount.address : fromAccount.toString();
71
+ const extra = new ExtraSignedExtension(api, {
72
+ signerAddress: address,
73
+ payloadOptions: options,
74
+ });
75
+ await extra.init();
76
+ const { signer } = options || {};
77
+ let signature;
78
+ if (isKeyringPair(fromAccount)) {
79
+ signature = u8aToHex(signRaw(fromAccount, extra.toRawPayload(this.callHex).data, { withType: true }));
80
+ }
81
+ else if (signer?.signPayload) {
82
+ const result = await signer.signPayload(extra.toPayload(this.callHex));
83
+ signature = result.signature;
84
+ }
85
+ else {
86
+ throw new Error('Signer not found. Cannot sign the extrinsic!');
87
+ }
88
+ const { signatureTypeId } = this.registry.metadata.extrinsic;
89
+ const $Signature = this.registry.findPortableCodec(signatureTypeId);
90
+ this.attachSignature({
91
+ address: address,
92
+ signature: $Signature.tryDecode(signature),
93
+ extra: extra.data,
94
+ });
95
+ return this;
96
+ }
97
+ async signAndSend(fromAccount, partialOptions, maybeCallback) {
98
+ const [options, callback] = this.#normalizeOptions(partialOptions, maybeCallback);
99
+ await this.sign(fromAccount, options);
100
+ return this.send(callback);
101
+ }
102
+ #normalizeOptions(partialOptions, callback) {
103
+ if (isFunction(partialOptions)) {
104
+ return [{}, partialOptions];
105
+ }
106
+ else {
107
+ return [objectSpread({}, partialOptions), callback];
108
+ }
109
+ }
110
+ async dryRun(account, optionsOrHash) {
111
+ const dryRunFn = api.rpc.system.dryRun;
112
+ assert(dryRunFn.meta, 'system_dryRun RPC does not supported!');
113
+ if (isHex(optionsOrHash)) {
114
+ return dryRunFn(this.toHex(), optionsOrHash);
115
+ }
116
+ await this.sign(account, optionsOrHash);
117
+ return dryRunFn(this.toHex());
118
+ }
119
+ async send(callback) {
120
+ const isSubscription = !!callback;
121
+ const txHash = this.hash;
122
+ if (isSubscription) {
123
+ return api.rpc.author.submitAndWatchExtrinsic(this.toHex(), async (status) => {
124
+ if (status.tag === 'InBlock' || status.tag === 'Finalized') {
125
+ const blockHash = status.value;
126
+ const [signedBlock, blockEvents] = await Promise.all([
127
+ api.rpc.chain.getBlock(blockHash),
128
+ api.queryAt(blockHash).system.events(),
129
+ ]);
130
+ const txIndex = signedBlock.block.extrinsics.findIndex((tx) => blake2AsHex(hexToU8a(tx)) === txHash);
131
+ assert(txIndex >= 0, 'Extrinsic not found!');
132
+ const events = blockEvents.filter(({ phase }) => phase.tag === 'ApplyExtrinsic' && phase.value === txIndex);
133
+ return callback(new SubmittableResult({ status, txHash, events, txIndex }));
134
+ }
135
+ else {
136
+ return callback(new SubmittableResult({ status, txHash }));
137
+ }
138
+ });
139
+ }
140
+ else {
141
+ return api.rpc.author.submitExtrinsic(this.toHex());
142
+ }
143
+ }
144
+ }
145
+ return new SubmittableExtrinsic(api.registry, call);
146
+ }
147
+ }
@@ -0,0 +1,8 @@
1
+ export * from './Executor';
2
+ export * from './RpcExecutor';
3
+ export * from './ConstantExecutor';
4
+ export * from './StorageQueryExecutor';
5
+ export * from './ErrorExecutor';
6
+ export * from './EventExecutor';
7
+ export * from './RuntimeApiExecutor';
8
+ export * from './TxExecutor';
@@ -0,0 +1,8 @@
1
+ export * from './Executor';
2
+ export * from './RpcExecutor';
3
+ export * from './ConstantExecutor';
4
+ export * from './StorageQueryExecutor';
5
+ export * from './ErrorExecutor';
6
+ export * from './EventExecutor';
7
+ export * from './RuntimeApiExecutor';
8
+ export * from './TxExecutor';