@dedot/api 0.0.1-alpha.32

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 (202) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1 -0
  3. package/chaintypes/index.d.ts +1 -0
  4. package/chaintypes/index.js +1 -0
  5. package/chaintypes/substrate/consts.d.ts +2132 -0
  6. package/chaintypes/substrate/consts.js +2 -0
  7. package/chaintypes/substrate/errors.d.ts +3490 -0
  8. package/chaintypes/substrate/errors.js +2 -0
  9. package/chaintypes/substrate/events.d.ts +5187 -0
  10. package/chaintypes/substrate/events.js +2 -0
  11. package/chaintypes/substrate/index.d.ts +22 -0
  12. package/chaintypes/substrate/index.js +2 -0
  13. package/chaintypes/substrate/json-rpc.d.ts +3 -0
  14. package/chaintypes/substrate/json-rpc.js +2 -0
  15. package/chaintypes/substrate/query.d.ts +3829 -0
  16. package/chaintypes/substrate/query.js +2 -0
  17. package/chaintypes/substrate/runtime.d.ts +850 -0
  18. package/chaintypes/substrate/runtime.js +2 -0
  19. package/chaintypes/substrate/tx.d.ts +14269 -0
  20. package/chaintypes/substrate/tx.js +2 -0
  21. package/chaintypes/substrate/types.d.ts +30457 -0
  22. package/chaintypes/substrate/types.js +2 -0
  23. package/cjs/chaintypes/index.js +17 -0
  24. package/cjs/chaintypes/substrate/consts.js +3 -0
  25. package/cjs/chaintypes/substrate/errors.js +3 -0
  26. package/cjs/chaintypes/substrate/events.js +3 -0
  27. package/cjs/chaintypes/substrate/index.js +18 -0
  28. package/cjs/chaintypes/substrate/json-rpc.js +3 -0
  29. package/cjs/chaintypes/substrate/query.js +3 -0
  30. package/cjs/chaintypes/substrate/runtime.js +3 -0
  31. package/cjs/chaintypes/substrate/tx.js +3 -0
  32. package/cjs/chaintypes/substrate/types.js +3 -0
  33. package/cjs/client/BaseSubstrateClient.js +257 -0
  34. package/cjs/client/Dedot.js +250 -0
  35. package/cjs/client/DedotClient.js +186 -0
  36. package/cjs/client/index.js +18 -0
  37. package/cjs/executor/ConstantExecutor.js +20 -0
  38. package/cjs/executor/ErrorExecutor.js +46 -0
  39. package/cjs/executor/EventExecutor.js +52 -0
  40. package/cjs/executor/Executor.js +42 -0
  41. package/cjs/executor/RuntimeApiExecutor.js +121 -0
  42. package/cjs/executor/StorageQueryExecutor.js +115 -0
  43. package/cjs/executor/TxExecutor.js +55 -0
  44. package/cjs/executor/index.js +26 -0
  45. package/cjs/executor/v2/RuntimeApiExecutorV2.js +21 -0
  46. package/cjs/executor/v2/StorageQueryExecutorV2.js +65 -0
  47. package/cjs/executor/v2/TxExecutorV2.js +20 -0
  48. package/cjs/extrinsic/extensions/ExtraSignedExtension.js +87 -0
  49. package/cjs/extrinsic/extensions/SignedExtension.js +41 -0
  50. package/cjs/extrinsic/extensions/index.js +19 -0
  51. package/cjs/extrinsic/extensions/known/ChargeAssetTxPayment.js +43 -0
  52. package/cjs/extrinsic/extensions/known/ChargeTransactionPayment.js +16 -0
  53. package/cjs/extrinsic/extensions/known/CheckGenesis.js +19 -0
  54. package/cjs/extrinsic/extensions/known/CheckMortality.js +90 -0
  55. package/cjs/extrinsic/extensions/known/CheckNonZeroSender.js +10 -0
  56. package/cjs/extrinsic/extensions/known/CheckNonce.js +33 -0
  57. package/cjs/extrinsic/extensions/known/CheckSpecVersion.js +19 -0
  58. package/cjs/extrinsic/extensions/known/CheckTxVersion.js +19 -0
  59. package/cjs/extrinsic/extensions/known/CheckWeight.js +10 -0
  60. package/cjs/extrinsic/extensions/known/PrevalidateAttests.js +11 -0
  61. package/cjs/extrinsic/extensions/known/index.js +25 -0
  62. package/cjs/extrinsic/index.js +18 -0
  63. package/cjs/extrinsic/submittable/BaseSubmittableExtrinsic.js +70 -0
  64. package/cjs/extrinsic/submittable/SubmittableExtrinsic.js +47 -0
  65. package/cjs/extrinsic/submittable/SubmittableExtrinsicV2.js +204 -0
  66. package/cjs/extrinsic/submittable/SubmittableResult.js +33 -0
  67. package/cjs/extrinsic/submittable/errors.js +16 -0
  68. package/cjs/extrinsic/submittable/fakeSigner.js +13 -0
  69. package/cjs/extrinsic/submittable/index.js +20 -0
  70. package/cjs/extrinsic/submittable/utils.js +20 -0
  71. package/cjs/index.js +21 -0
  72. package/cjs/json-rpc/JsonRpcClient.js +165 -0
  73. package/cjs/json-rpc/group/ChainHead/BlockUsage.js +24 -0
  74. package/cjs/json-rpc/group/ChainHead/ChainHead.js +603 -0
  75. package/cjs/json-rpc/group/ChainHead/error.js +59 -0
  76. package/cjs/json-rpc/group/ChainHead/index.js +18 -0
  77. package/cjs/json-rpc/group/ChainSpec.js +19 -0
  78. package/cjs/json-rpc/group/JsonRpcGroup.js +89 -0
  79. package/cjs/json-rpc/group/Transaction.js +25 -0
  80. package/cjs/json-rpc/group/TransactionWatch.js +17 -0
  81. package/cjs/json-rpc/group/index.js +21 -0
  82. package/cjs/json-rpc/index.js +20 -0
  83. package/cjs/json-rpc/scaledResponses.js +15 -0
  84. package/cjs/json-rpc/subscriptionsInfo.js +20 -0
  85. package/cjs/package.json +1 -0
  86. package/cjs/proxychain.js +27 -0
  87. package/cjs/storage/QueryableStorage.js +161 -0
  88. package/cjs/storage/index.js +17 -0
  89. package/cjs/types.js +2 -0
  90. package/client/BaseSubstrateClient.d.ts +65 -0
  91. package/client/BaseSubstrateClient.js +252 -0
  92. package/client/Dedot.d.ts +131 -0
  93. package/client/Dedot.js +246 -0
  94. package/client/DedotClient.d.ts +61 -0
  95. package/client/DedotClient.js +182 -0
  96. package/client/index.d.ts +2 -0
  97. package/client/index.js +2 -0
  98. package/executor/ConstantExecutor.d.ts +10 -0
  99. package/executor/ConstantExecutor.js +16 -0
  100. package/executor/ErrorExecutor.d.ts +10 -0
  101. package/executor/ErrorExecutor.js +42 -0
  102. package/executor/EventExecutor.d.ts +10 -0
  103. package/executor/EventExecutor.js +48 -0
  104. package/executor/Executor.d.ts +149 -0
  105. package/executor/Executor.js +38 -0
  106. package/executor/RuntimeApiExecutor.d.ts +27 -0
  107. package/executor/RuntimeApiExecutor.js +117 -0
  108. package/executor/StorageQueryExecutor.d.ts +14 -0
  109. package/executor/StorageQueryExecutor.js +111 -0
  110. package/executor/TxExecutor.d.ts +10 -0
  111. package/executor/TxExecutor.js +51 -0
  112. package/executor/index.d.ts +10 -0
  113. package/executor/index.js +10 -0
  114. package/executor/v2/RuntimeApiExecutorV2.d.ts +14 -0
  115. package/executor/v2/RuntimeApiExecutorV2.js +17 -0
  116. package/executor/v2/StorageQueryExecutorV2.d.ts +17 -0
  117. package/executor/v2/StorageQueryExecutorV2.js +61 -0
  118. package/executor/v2/TxExecutorV2.d.ts +11 -0
  119. package/executor/v2/TxExecutorV2.js +16 -0
  120. package/extrinsic/extensions/ExtraSignedExtension.d.ts +14 -0
  121. package/extrinsic/extensions/ExtraSignedExtension.js +60 -0
  122. package/extrinsic/extensions/SignedExtension.d.ts +40 -0
  123. package/extrinsic/extensions/SignedExtension.js +37 -0
  124. package/extrinsic/extensions/index.d.ts +3 -0
  125. package/extrinsic/extensions/index.js +3 -0
  126. package/extrinsic/extensions/known/ChargeAssetTxPayment.d.ts +14 -0
  127. package/extrinsic/extensions/known/ChargeAssetTxPayment.js +39 -0
  128. package/extrinsic/extensions/known/ChargeTransactionPayment.d.ts +6 -0
  129. package/extrinsic/extensions/known/ChargeTransactionPayment.js +12 -0
  130. package/extrinsic/extensions/known/CheckGenesis.d.ts +10 -0
  131. package/extrinsic/extensions/known/CheckGenesis.js +15 -0
  132. package/extrinsic/extensions/known/CheckMortality.d.ts +15 -0
  133. package/extrinsic/extensions/known/CheckMortality.js +86 -0
  134. package/extrinsic/extensions/known/CheckNonZeroSender.d.ts +6 -0
  135. package/extrinsic/extensions/known/CheckNonZeroSender.js +6 -0
  136. package/extrinsic/extensions/known/CheckNonce.d.ts +10 -0
  137. package/extrinsic/extensions/known/CheckNonce.js +29 -0
  138. package/extrinsic/extensions/known/CheckSpecVersion.d.ts +9 -0
  139. package/extrinsic/extensions/known/CheckSpecVersion.js +15 -0
  140. package/extrinsic/extensions/known/CheckTxVersion.d.ts +9 -0
  141. package/extrinsic/extensions/known/CheckTxVersion.js +15 -0
  142. package/extrinsic/extensions/known/CheckWeight.d.ts +6 -0
  143. package/extrinsic/extensions/known/CheckWeight.js +6 -0
  144. package/extrinsic/extensions/known/PrevalidateAttests.d.ts +7 -0
  145. package/extrinsic/extensions/known/PrevalidateAttests.js +7 -0
  146. package/extrinsic/extensions/known/index.d.ts +3 -0
  147. package/extrinsic/extensions/known/index.js +22 -0
  148. package/extrinsic/index.d.ts +2 -0
  149. package/extrinsic/index.js +2 -0
  150. package/extrinsic/submittable/BaseSubmittableExtrinsic.d.ts +17 -0
  151. package/extrinsic/submittable/BaseSubmittableExtrinsic.js +66 -0
  152. package/extrinsic/submittable/SubmittableExtrinsic.d.ts +12 -0
  153. package/extrinsic/submittable/SubmittableExtrinsic.js +43 -0
  154. package/extrinsic/submittable/SubmittableExtrinsicV2.d.ts +15 -0
  155. package/extrinsic/submittable/SubmittableExtrinsicV2.js +200 -0
  156. package/extrinsic/submittable/SubmittableResult.d.ts +19 -0
  157. package/extrinsic/submittable/SubmittableResult.js +29 -0
  158. package/extrinsic/submittable/errors.d.ts +11 -0
  159. package/extrinsic/submittable/errors.js +12 -0
  160. package/extrinsic/submittable/fakeSigner.d.ts +2 -0
  161. package/extrinsic/submittable/fakeSigner.js +10 -0
  162. package/extrinsic/submittable/index.d.ts +4 -0
  163. package/extrinsic/submittable/index.js +4 -0
  164. package/extrinsic/submittable/utils.d.ts +10 -0
  165. package/extrinsic/submittable/utils.js +15 -0
  166. package/index.d.ts +6 -0
  167. package/index.js +5 -0
  168. package/json-rpc/JsonRpcClient.d.ts +50 -0
  169. package/json-rpc/JsonRpcClient.js +160 -0
  170. package/json-rpc/group/ChainHead/BlockUsage.d.ts +11 -0
  171. package/json-rpc/group/ChainHead/BlockUsage.js +20 -0
  172. package/json-rpc/group/ChainHead/ChainHead.d.ts +70 -0
  173. package/json-rpc/group/ChainHead/ChainHead.js +599 -0
  174. package/json-rpc/group/ChainHead/error.d.ts +47 -0
  175. package/json-rpc/group/ChainHead/error.js +48 -0
  176. package/json-rpc/group/ChainHead/index.d.ts +2 -0
  177. package/json-rpc/group/ChainHead/index.js +2 -0
  178. package/json-rpc/group/ChainSpec.d.ts +10 -0
  179. package/json-rpc/group/ChainSpec.js +15 -0
  180. package/json-rpc/group/JsonRpcGroup.d.ts +74 -0
  181. package/json-rpc/group/JsonRpcGroup.js +85 -0
  182. package/json-rpc/group/Transaction.d.ts +11 -0
  183. package/json-rpc/group/Transaction.js +21 -0
  184. package/json-rpc/group/TransactionWatch.d.ts +10 -0
  185. package/json-rpc/group/TransactionWatch.js +13 -0
  186. package/json-rpc/group/index.d.ts +5 -0
  187. package/json-rpc/group/index.js +5 -0
  188. package/json-rpc/index.d.ts +4 -0
  189. package/json-rpc/index.js +4 -0
  190. package/json-rpc/scaledResponses.d.ts +2 -0
  191. package/json-rpc/scaledResponses.js +12 -0
  192. package/json-rpc/subscriptionsInfo.d.ts +2 -0
  193. package/json-rpc/subscriptionsInfo.js +17 -0
  194. package/package.json +54 -0
  195. package/proxychain.d.ts +14 -0
  196. package/proxychain.js +23 -0
  197. package/storage/QueryableStorage.d.ts +35 -0
  198. package/storage/QueryableStorage.js +157 -0
  199. package/storage/index.d.ts +1 -0
  200. package/storage/index.js +1 -0
  201. package/types.d.ts +120 -0
  202. package/types.js +1 -0
@@ -0,0 +1,252 @@
1
+ import { $Metadata, PortableRegistry } from '@dedot/codecs';
2
+ import { LocalStorage } from '@dedot/storage';
3
+ import { calcRuntimeApiHash, ensurePresence as _ensurePresence, u8aToHex } from '@dedot/utils';
4
+ import { ConstantExecutor, ErrorExecutor, EventExecutor } from '../executor/index.js';
5
+ import { isJsonRpcProvider, JsonRpcClient } from '../json-rpc/index.js';
6
+ import { newProxyChain } from '../proxychain.js';
7
+ const SUPPORTED_METADATA_VERSIONS = [15, 14];
8
+ const MetadataApiHash = calcRuntimeApiHash('Metadata'); // 0x37e397fc7c91f5e4
9
+ const MESSAGE = 'Make sure to call `.connect()` method first before using the API interfaces.';
10
+ export function ensurePresence(value) {
11
+ return _ensurePresence(value, MESSAGE);
12
+ }
13
+ /**
14
+ * @name BaseSubstrateClient
15
+ * @description Base & shared abstraction for Substrate API Clients
16
+ */
17
+ export class BaseSubstrateClient extends JsonRpcClient {
18
+ rpcVersion;
19
+ _options;
20
+ _registry;
21
+ _metadata;
22
+ _genesisHash;
23
+ _runtimeVersion;
24
+ _localCache;
25
+ constructor(rpcVersion, options) {
26
+ super(options);
27
+ this.rpcVersion = rpcVersion;
28
+ this._options = this.normalizeOptions(options);
29
+ }
30
+ /// --- Internal logics
31
+ normalizeOptions(options) {
32
+ const defaultOptions = { throwOnUnknownApi: true };
33
+ if (isJsonRpcProvider(options)) {
34
+ return { ...defaultOptions, provider: options };
35
+ }
36
+ else {
37
+ return { ...defaultOptions, ...options };
38
+ }
39
+ }
40
+ async initializeLocalCache() {
41
+ if (!this._options.cacheMetadata)
42
+ return;
43
+ // Initialize local cache
44
+ if (this._options.cacheStorage) {
45
+ this._localCache = this._options.cacheStorage;
46
+ return;
47
+ }
48
+ try {
49
+ this._localCache = new LocalStorage();
50
+ }
51
+ catch {
52
+ throw new Error('localStorage is not available for caching, please provide a cacheStorage option');
53
+ }
54
+ }
55
+ async setupMetadata(preloadMetadata) {
56
+ let metadata = preloadMetadata;
57
+ let shouldUpdateCache = !!metadata;
58
+ if (!metadata) {
59
+ metadata = this.getMetadataFromOptions(this._runtimeVersion);
60
+ }
61
+ const metadataKey = this.currentMetadataKey;
62
+ try {
63
+ if (this._localCache && this._options.cacheMetadata) {
64
+ if (!metadata) {
65
+ try {
66
+ const cachedRawMetadata = await this._localCache.get(metadataKey);
67
+ if (cachedRawMetadata) {
68
+ metadata = $Metadata.tryDecode(cachedRawMetadata);
69
+ }
70
+ }
71
+ catch (e) {
72
+ console.error('Cannot decode raw metadata, try fetching fresh metadata from chain.', e);
73
+ }
74
+ }
75
+ }
76
+ }
77
+ finally {
78
+ if (!metadata) {
79
+ metadata = await this.fetchMetadata();
80
+ if (this._options.cacheMetadata)
81
+ shouldUpdateCache = true;
82
+ }
83
+ }
84
+ if (shouldUpdateCache && this._localCache) {
85
+ await this._localCache.set(metadataKey, u8aToHex($Metadata.tryEncode(metadata)));
86
+ }
87
+ if (!metadata) {
88
+ throw new Error('Cannot load metadata');
89
+ }
90
+ this.setMetadata(metadata);
91
+ }
92
+ setMetadata(metadata) {
93
+ this._metadata = metadata;
94
+ this._registry = new PortableRegistry(metadata.latest, this.options.hasher);
95
+ }
96
+ getMetadataKey(runtime) {
97
+ return `RAW_META/${this._genesisHash || '0x'}/${runtime?.specVersion || '---'}`;
98
+ }
99
+ get currentMetadataKey() {
100
+ return this.getMetadataKey(this._runtimeVersion);
101
+ }
102
+ async shouldPreloadMetadata() {
103
+ if (this._options.metadata && Object.keys(this._options.metadata).length) {
104
+ return false;
105
+ }
106
+ if (!this._options.cacheMetadata || !this._localCache) {
107
+ return true;
108
+ }
109
+ // TODO improve this
110
+ const keys = await this._localCache.keys();
111
+ return !keys.some((k) => k.startsWith('RAW_META/'));
112
+ }
113
+ getMetadataFromOptions(runtime) {
114
+ if (!runtime || !this.options.metadata)
115
+ return;
116
+ const key = this.getMetadataKey(runtime);
117
+ if (this.options.metadata[key]) {
118
+ return $Metadata.tryDecode(this.options.metadata[key]);
119
+ }
120
+ }
121
+ async fetchMetadata(hash, runtime) {
122
+ // First try finding metadata from the provided option
123
+ const optionMetadata = this.getMetadataFromOptions(runtime);
124
+ if (optionMetadata)
125
+ return optionMetadata;
126
+ // If there is no runtime, we assume that the node supports Metadata Api V2
127
+ const supportedV2 = runtime ? runtime.apis[MetadataApiHash] === 2 : true;
128
+ if (supportedV2) {
129
+ // It makes sense to call metadata.metadataVersions to fetch the list of supported metadata versions first
130
+ // But for now, this approach could potentially help save/reduce one rpc call to the server in case the node support v15
131
+ // Question: Why not having a `metadata.metadataLatest` to fetch the latest version?
132
+ for (const version of SUPPORTED_METADATA_VERSIONS) {
133
+ try {
134
+ const rawMetadata = await this.callAt(hash).metadata.metadataAtVersion(version);
135
+ if (!rawMetadata)
136
+ continue;
137
+ return $Metadata.tryDecode(rawMetadata);
138
+ }
139
+ catch { }
140
+ }
141
+ }
142
+ try {
143
+ return $Metadata.tryDecode(await this.callAt(hash).metadata.metadata());
144
+ }
145
+ catch {
146
+ return await this.rpc.state_getMetadata();
147
+ }
148
+ }
149
+ cleanUp() {
150
+ this._registry = undefined;
151
+ this._metadata = undefined;
152
+ this._genesisHash = undefined;
153
+ this._runtimeVersion = undefined;
154
+ this._localCache = undefined;
155
+ }
156
+ /**
157
+ * @description Clear local cache
158
+ */
159
+ async clearCache() {
160
+ await this._localCache?.clear();
161
+ }
162
+ async doConnect() {
163
+ this.on('connected', this.onConnected);
164
+ this.on('disconnected', this.onDisconnected);
165
+ return new Promise((resolve) => {
166
+ this.once('ready', () => {
167
+ resolve(this);
168
+ });
169
+ });
170
+ }
171
+ onConnected = async () => {
172
+ await this.initialize();
173
+ };
174
+ onDisconnected = async () => { };
175
+ async initialize() {
176
+ await this.initializeLocalCache();
177
+ await this.doInitialize();
178
+ this.emit('ready');
179
+ }
180
+ async doInitialize() {
181
+ throw new Error('Unimplemented!');
182
+ }
183
+ async beforeDisconnect() { }
184
+ async afterDisconnect() {
185
+ this.cleanUp();
186
+ }
187
+ toSubstrateRuntimeVersion(runtimeVersion) {
188
+ return {
189
+ ...runtimeVersion,
190
+ apis: runtimeVersion.apis.reduce((o, [name, version]) => {
191
+ o[name] = version;
192
+ return o;
193
+ }, {}),
194
+ };
195
+ }
196
+ /// --- Public APIs ---
197
+ /**
198
+ * @description Connect to blockchain node
199
+ */
200
+ async connect() {
201
+ const [api, _] = await Promise.all([this.doConnect(), super.connect()]);
202
+ return api;
203
+ }
204
+ /**
205
+ * @description Disconnect to blockchain node
206
+ */
207
+ async disconnect() {
208
+ await this.beforeDisconnect();
209
+ await super.disconnect();
210
+ await this.afterDisconnect();
211
+ }
212
+ get options() {
213
+ return this._options;
214
+ }
215
+ get metadata() {
216
+ return ensurePresence(this._metadata);
217
+ }
218
+ get registry() {
219
+ return ensurePresence(this._registry);
220
+ }
221
+ get genesisHash() {
222
+ return ensurePresence(this._genesisHash);
223
+ }
224
+ get runtimeVersion() {
225
+ return ensurePresence(this._runtimeVersion);
226
+ }
227
+ get consts() {
228
+ return newProxyChain({ executor: new ConstantExecutor(this) });
229
+ }
230
+ get errors() {
231
+ return newProxyChain({ executor: new ErrorExecutor(this) });
232
+ }
233
+ get events() {
234
+ return newProxyChain({ executor: new EventExecutor(this) });
235
+ }
236
+ get query() {
237
+ throw new Error('Unimplemented!');
238
+ }
239
+ get call() {
240
+ return this.callAt();
241
+ }
242
+ // For internal use with caution
243
+ callAt(hash) {
244
+ throw new Error('Unimplemented!');
245
+ }
246
+ get tx() {
247
+ throw new Error('Unimplemented!');
248
+ }
249
+ at(hash) {
250
+ throw new Error('Unimplemented!');
251
+ }
252
+ }
@@ -0,0 +1,131 @@
1
+ import { BlockHash } from '@dedot/codecs';
2
+ import type { JsonRpcProvider } from '@dedot/providers';
3
+ import { GenericSubstrateApi, RpcLegacy, VersionedGenericSubstrateApi } from '@dedot/types';
4
+ import type { SubstrateApi } from '../chaintypes/index.js';
5
+ import type { ApiOptions, ISubstrateClientAt } from '../types.js';
6
+ import { BaseSubstrateClient } from './BaseSubstrateClient.js';
7
+ /**
8
+ * @name Dedot
9
+ * @description Promised-based API Client for Polkadot & Substrate
10
+ *
11
+ * Initialize API instance and interact with substrate-based network
12
+ * ```typescript
13
+ * import { Dedot } from 'dedot';
14
+ * import type { PolkadotApi } from '@dedot/chaintypes/polkadot';
15
+ *
16
+ * const run = async () => {
17
+ * const api = await Dedot.new<PolkadotApi>('wss://rpc.polkadot.io');
18
+ *
19
+ * // Call rpc `state_getMetadata` to fetch raw scale-encoded metadata and decode it.
20
+ * const metadata = await api.rpc.state.getMetadata();
21
+ * console.log('Metadata:', metadata);
22
+ *
23
+ * // Query on-chain storage
24
+ * const address = '14...';
25
+ * const balance = await api.query.system.account(address);
26
+ * console.log('Balance:', balance);
27
+ *
28
+ *
29
+ * // Subscribe to on-chain storage changes
30
+ * const unsub = await api.query.system.number((blockNumber) => {
31
+ * console.log(`Current block number: ${blockNumber}`);
32
+ * });
33
+ *
34
+ * // Get pallet constants
35
+ * const ss58Prefix = api.consts.system.ss58Prefix;
36
+ * console.log('Polkadot ss58Prefix:', ss58Prefix)
37
+ *
38
+ * // await unsub();
39
+ * // await api.disconnect();
40
+ * }
41
+ *
42
+ * run().catch(console.error);
43
+ * ```
44
+ */
45
+ export declare class Dedot<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends BaseSubstrateClient<ChainApi> {
46
+ #private;
47
+ /**
48
+ * Use factory methods (`create`, `new`) to create `Dedot` instances.
49
+ *
50
+ * @param options
51
+ */
52
+ constructor(options: ApiOptions | JsonRpcProvider);
53
+ /**
54
+ * Factory method to create a new Dedot instance
55
+ *
56
+ * @param options
57
+ */
58
+ static create<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi>(options: ApiOptions | JsonRpcProvider): Promise<Dedot<ChainApi>>;
59
+ /**
60
+ * Alias for __Dedot.create__
61
+ *
62
+ * @param options
63
+ */
64
+ static new<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi>(options: ApiOptions | JsonRpcProvider): Promise<Dedot<ChainApi>>;
65
+ protected onDisconnected: () => Promise<void>;
66
+ protected beforeDisconnect(): Promise<void>;
67
+ /**
68
+ * Initialize APIs before usage
69
+ */
70
+ protected doInitialize(): Promise<void>;
71
+ protected cleanUp(): void;
72
+ /**
73
+ * @description Entry-point for inspecting constants (parameter types) for all pallets (modules).
74
+ *
75
+ * ```typescript
76
+ * const ss58Prefix = api.consts.system.ss58Prefix;
77
+ * console.log('ss58Prefix:', ss58Prefix)
78
+ * ```
79
+ */
80
+ get consts(): ChainApi[RpcLegacy]['consts'];
81
+ /**
82
+ * @description Entry-point for executing query to on-chain storage.
83
+ *
84
+ * ```typescript
85
+ * const balance = await api.query.system.account(<address>);
86
+ * console.log('Balance:', balance);
87
+ * ```
88
+ */
89
+ get query(): ChainApi[RpcLegacy]['query'];
90
+ /**
91
+ * @description Entry-point for inspecting errors from metadata
92
+ */
93
+ get errors(): ChainApi[RpcLegacy]['errors'];
94
+ /**
95
+ * @description Entry-point for inspecting events from metadata
96
+ */
97
+ get events(): ChainApi[RpcLegacy]['events'];
98
+ /**
99
+ * @description Entry-point for executing runtime api
100
+ *
101
+ * ```typescript
102
+ * // Get account nonce
103
+ * const nonce = await api.call.accountNonceApi.accountNonce(<address>);
104
+ *
105
+ * // Query transaction payment info
106
+ * const tx = api.tx.balances.transferKeepAlive(<address>, 2_000_000_000_000n);
107
+ * const queryInfo = await api.call.transactionPaymentApi.queryInfo(tx.toU8a(), tx.length);
108
+ * ```
109
+ */
110
+ get call(): ChainApi[RpcLegacy]['call'];
111
+ protected callAt(hash?: BlockHash): ChainApi[RpcLegacy]['call'];
112
+ /**
113
+ * @description Entry-point for executing on-chain transactions
114
+ *
115
+ * ```typescript
116
+ * // Make a transfer balance transaction
117
+ * api.tx.balances.transferKeepAlive(<address>, <amount>)
118
+ * .signAndSend(<keyPair|address>, { signer }, ({ status }) => {
119
+ * console.log('Transaction status', status.tag);
120
+ * });
121
+ * ```
122
+ */
123
+ get tx(): ChainApi[RpcLegacy]['tx'];
124
+ /**
125
+ * Create a new API instance at a specific block hash
126
+ * This is useful when we want to inspect the state of the chain at a specific block hash
127
+ *
128
+ * @param hash
129
+ */
130
+ at<ChainApiAt extends GenericSubstrateApi = ChainApi[RpcLegacy]>(hash: BlockHash): Promise<ISubstrateClientAt<ChainApiAt>>;
131
+ }
@@ -0,0 +1,246 @@
1
+ import { PortableRegistry } from '@dedot/codecs';
2
+ import { ConstantExecutor, ErrorExecutor, EventExecutor, RuntimeApiExecutor, StorageQueryExecutor, TxExecutor, } from '../executor/index.js';
3
+ import { newProxyChain } from '../proxychain.js';
4
+ import { BaseSubstrateClient } from './BaseSubstrateClient.js';
5
+ const KEEP_ALIVE_INTERVAL = 10_000; // in ms
6
+ /**
7
+ * @name Dedot
8
+ * @description Promised-based API Client for Polkadot & Substrate
9
+ *
10
+ * Initialize API instance and interact with substrate-based network
11
+ * ```typescript
12
+ * import { Dedot } from 'dedot';
13
+ * import type { PolkadotApi } from '@dedot/chaintypes/polkadot';
14
+ *
15
+ * const run = async () => {
16
+ * const api = await Dedot.new<PolkadotApi>('wss://rpc.polkadot.io');
17
+ *
18
+ * // Call rpc `state_getMetadata` to fetch raw scale-encoded metadata and decode it.
19
+ * const metadata = await api.rpc.state.getMetadata();
20
+ * console.log('Metadata:', metadata);
21
+ *
22
+ * // Query on-chain storage
23
+ * const address = '14...';
24
+ * const balance = await api.query.system.account(address);
25
+ * console.log('Balance:', balance);
26
+ *
27
+ *
28
+ * // Subscribe to on-chain storage changes
29
+ * const unsub = await api.query.system.number((blockNumber) => {
30
+ * console.log(`Current block number: ${blockNumber}`);
31
+ * });
32
+ *
33
+ * // Get pallet constants
34
+ * const ss58Prefix = api.consts.system.ss58Prefix;
35
+ * console.log('Polkadot ss58Prefix:', ss58Prefix)
36
+ *
37
+ * // await unsub();
38
+ * // await api.disconnect();
39
+ * }
40
+ *
41
+ * run().catch(console.error);
42
+ * ```
43
+ */
44
+ export class Dedot extends BaseSubstrateClient {
45
+ #runtimeSubscriptionUnsub;
46
+ #healthTimer;
47
+ #apiAtCache = {};
48
+ /**
49
+ * Use factory methods (`create`, `new`) to create `Dedot` instances.
50
+ *
51
+ * @param options
52
+ */
53
+ constructor(options) {
54
+ super('legacy', options);
55
+ }
56
+ /**
57
+ * Factory method to create a new Dedot instance
58
+ *
59
+ * @param options
60
+ */
61
+ static async create(options) {
62
+ return new Dedot(options).connect();
63
+ }
64
+ /**
65
+ * Alias for __Dedot.create__
66
+ *
67
+ * @param options
68
+ */
69
+ static async new(options) {
70
+ return Dedot.create(options);
71
+ }
72
+ onDisconnected = async () => {
73
+ await this.#unsubscribeUpdates();
74
+ };
75
+ async beforeDisconnect() {
76
+ await this.#unsubscribeUpdates();
77
+ }
78
+ /**
79
+ * Initialize APIs before usage
80
+ */
81
+ async doInitialize() {
82
+ let [genesisHash, runtimeVersion, metadata] = await Promise.all([
83
+ this.rpc.chain_getBlockHash(0),
84
+ this.#getRuntimeVersion(),
85
+ (await this.shouldPreloadMetadata()) ? this.fetchMetadata() : Promise.resolve(undefined),
86
+ ]);
87
+ this._genesisHash = genesisHash;
88
+ this._runtimeVersion = runtimeVersion;
89
+ await this.setupMetadata(metadata);
90
+ this.#subscribeUpdates();
91
+ }
92
+ cleanUp() {
93
+ super.cleanUp();
94
+ this.#apiAtCache = {};
95
+ this.#healthTimer = undefined;
96
+ this.#runtimeSubscriptionUnsub = undefined;
97
+ }
98
+ #subscribeRuntimeUpgrades() {
99
+ if (this.#runtimeSubscriptionUnsub)
100
+ return;
101
+ this.rpc
102
+ .state_subscribeRuntimeVersion(async (runtimeVersion) => {
103
+ if (runtimeVersion.specVersion !== this.runtimeVersion?.specVersion) {
104
+ this._runtimeVersion = this.toSubstrateRuntimeVersion(runtimeVersion);
105
+ const newMetadata = await this.fetchMetadata(undefined, this._runtimeVersion);
106
+ await this.setupMetadata(newMetadata);
107
+ }
108
+ })
109
+ .then((unsub) => {
110
+ this.#runtimeSubscriptionUnsub = unsub;
111
+ });
112
+ }
113
+ async #getRuntimeVersion(at) {
114
+ return this.toSubstrateRuntimeVersion(await this.rpc.state_getRuntimeVersion(at));
115
+ }
116
+ #subscribeHealth() {
117
+ this.#unsubscribeHealth();
118
+ this.#healthTimer = setInterval(() => {
119
+ this.rpc.system_health().catch(console.error);
120
+ }, KEEP_ALIVE_INTERVAL);
121
+ }
122
+ #unsubscribeHealth() {
123
+ if (!this.#healthTimer) {
124
+ return;
125
+ }
126
+ clearInterval(this.#healthTimer);
127
+ this.#healthTimer = undefined;
128
+ }
129
+ async #unsubscribeRuntimeUpdates() {
130
+ if (!this.#runtimeSubscriptionUnsub) {
131
+ return;
132
+ }
133
+ await this.#runtimeSubscriptionUnsub();
134
+ this.#runtimeSubscriptionUnsub = undefined;
135
+ }
136
+ #subscribeUpdates() {
137
+ this.#subscribeRuntimeUpgrades();
138
+ this.#subscribeHealth();
139
+ }
140
+ async #unsubscribeUpdates() {
141
+ await this.#unsubscribeRuntimeUpdates();
142
+ this.#unsubscribeHealth();
143
+ }
144
+ /// --- Public APIs ---
145
+ /**
146
+ * @description Entry-point for inspecting constants (parameter types) for all pallets (modules).
147
+ *
148
+ * ```typescript
149
+ * const ss58Prefix = api.consts.system.ss58Prefix;
150
+ * console.log('ss58Prefix:', ss58Prefix)
151
+ * ```
152
+ */
153
+ get consts() {
154
+ return newProxyChain({ executor: new ConstantExecutor(this) });
155
+ }
156
+ /**
157
+ * @description Entry-point for executing query to on-chain storage.
158
+ *
159
+ * ```typescript
160
+ * const balance = await api.query.system.account(<address>);
161
+ * console.log('Balance:', balance);
162
+ * ```
163
+ */
164
+ get query() {
165
+ return newProxyChain({ executor: new StorageQueryExecutor(this) });
166
+ }
167
+ /**
168
+ * @description Entry-point for inspecting errors from metadata
169
+ */
170
+ get errors() {
171
+ return newProxyChain({ executor: new ErrorExecutor(this) });
172
+ }
173
+ /**
174
+ * @description Entry-point for inspecting events from metadata
175
+ */
176
+ get events() {
177
+ return newProxyChain({ executor: new EventExecutor(this) });
178
+ }
179
+ /**
180
+ * @description Entry-point for executing runtime api
181
+ *
182
+ * ```typescript
183
+ * // Get account nonce
184
+ * const nonce = await api.call.accountNonceApi.accountNonce(<address>);
185
+ *
186
+ * // Query transaction payment info
187
+ * const tx = api.tx.balances.transferKeepAlive(<address>, 2_000_000_000_000n);
188
+ * const queryInfo = await api.call.transactionPaymentApi.queryInfo(tx.toU8a(), tx.length);
189
+ * ```
190
+ */
191
+ get call() {
192
+ return this.callAt();
193
+ }
194
+ // For internal use with caution
195
+ callAt(hash) {
196
+ return newProxyChain({ executor: new RuntimeApiExecutor(this, hash) });
197
+ }
198
+ /**
199
+ * @description Entry-point for executing on-chain transactions
200
+ *
201
+ * ```typescript
202
+ * // Make a transfer balance transaction
203
+ * api.tx.balances.transferKeepAlive(<address>, <amount>)
204
+ * .signAndSend(<keyPair|address>, { signer }, ({ status }) => {
205
+ * console.log('Transaction status', status.tag);
206
+ * });
207
+ * ```
208
+ */
209
+ get tx() {
210
+ return newProxyChain({ executor: new TxExecutor(this) });
211
+ }
212
+ /**
213
+ * Create a new API instance at a specific block hash
214
+ * This is useful when we want to inspect the state of the chain at a specific block hash
215
+ *
216
+ * @param hash
217
+ */
218
+ async at(hash) {
219
+ if (this.#apiAtCache[hash])
220
+ return this.#apiAtCache[hash];
221
+ const targetVersion = await this.#getRuntimeVersion(hash);
222
+ let metadata = this.metadata;
223
+ let registry = this.registry;
224
+ if (targetVersion.specVersion !== this.runtimeVersion.specVersion) {
225
+ metadata = await this.fetchMetadata(hash, targetVersion);
226
+ registry = new PortableRegistry(metadata.latest, this.options.hasher);
227
+ }
228
+ const api = {
229
+ rpcVersion: 'legacy',
230
+ atBlockHash: hash,
231
+ options: this.options,
232
+ genesisHash: this.genesisHash,
233
+ runtimeVersion: targetVersion,
234
+ metadata,
235
+ registry,
236
+ rpc: this.rpc,
237
+ };
238
+ api.consts = newProxyChain({ executor: new ConstantExecutor(api) });
239
+ api.query = newProxyChain({ executor: new StorageQueryExecutor(api) });
240
+ api.call = newProxyChain({ executor: new RuntimeApiExecutor(api) });
241
+ api.events = newProxyChain({ executor: new EventExecutor(api) });
242
+ api.errors = newProxyChain({ executor: new ErrorExecutor(api) });
243
+ this.#apiAtCache[hash] = api;
244
+ return api;
245
+ }
246
+ }
@@ -0,0 +1,61 @@
1
+ import { BlockHash } from '@dedot/codecs';
2
+ import type { JsonRpcProvider } from '@dedot/providers';
3
+ import { GenericSubstrateApi, RpcV2, VersionedGenericSubstrateApi } from '@dedot/types';
4
+ import type { SubstrateApi } from '../chaintypes/index.js';
5
+ import { ChainHead, ChainSpec, PinnedBlock } from '../json-rpc/index.js';
6
+ import type { ApiOptions, ISubstrateClientAt, TxBroadcaster } from '../types.js';
7
+ import { BaseSubstrateClient } from './BaseSubstrateClient.js';
8
+ /**
9
+ * @name DedotClient
10
+ * @description New promised-based API Client for Polkadot & Substrate based on JSON-RPC V2
11
+ *
12
+ * __Unstable, use with caution.__
13
+ */
14
+ export declare class DedotClient<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends BaseSubstrateClient<ChainApi> {
15
+ #private;
16
+ protected _chainHead?: ChainHead;
17
+ protected _chainSpec?: ChainSpec;
18
+ protected _txBroadcaster?: TxBroadcaster;
19
+ /**
20
+ * Use factory methods (`create`, `new`) to create `DedotClient` instances.
21
+ *
22
+ * @param options
23
+ */
24
+ constructor(options: ApiOptions | JsonRpcProvider);
25
+ /**
26
+ * Factory method to create a new DedotClient instance
27
+ *
28
+ * @param options
29
+ */
30
+ static create<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi>(options: ApiOptions | JsonRpcProvider): Promise<DedotClient<ChainApi>>;
31
+ /**
32
+ * Alias for __DedotClient.create__
33
+ *
34
+ * @param options
35
+ */
36
+ static new<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi>(options: ApiOptions | JsonRpcProvider): Promise<DedotClient<ChainApi>>;
37
+ get chainSpec(): ChainSpec;
38
+ get chainHead(): ChainHead;
39
+ get txBroadcaster(): TxBroadcaster;
40
+ /**
41
+ * Initialize APIs before usage
42
+ */
43
+ protected doInitialize(): Promise<void>;
44
+ protected subscribeRuntimeUpgrades(): void;
45
+ protected unsubscribeRuntimeUpgrades(): void;
46
+ protected onRuntimeUpgrade: (block: PinnedBlock) => Promise<void>;
47
+ protected beforeDisconnect(): Promise<void>;
48
+ protected onDisconnected: () => Promise<void>;
49
+ protected cleanUp(): void;
50
+ get query(): ChainApi[RpcV2]['query'];
51
+ get call(): ChainApi[RpcV2]['call'];
52
+ protected callAt(blockHash?: BlockHash): ChainApi[RpcV2]['call'];
53
+ get tx(): ChainApi[RpcV2]['tx'];
54
+ /**
55
+ * Get a new API instance at a specific block hash
56
+ * For now, this only supports pinned block hashes from the chain head
57
+ *
58
+ * @param hash
59
+ */
60
+ at<ChainApiAt extends GenericSubstrateApi = ChainApi[RpcV2]>(hash: BlockHash): Promise<ISubstrateClientAt<ChainApiAt>>;
61
+ }