@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.
- package/LICENSE +201 -0
- package/README.md +1 -0
- package/chaintypes/index.d.ts +1 -0
- package/chaintypes/index.js +1 -0
- package/chaintypes/substrate/consts.d.ts +2132 -0
- package/chaintypes/substrate/consts.js +2 -0
- package/chaintypes/substrate/errors.d.ts +3490 -0
- package/chaintypes/substrate/errors.js +2 -0
- package/chaintypes/substrate/events.d.ts +5187 -0
- package/chaintypes/substrate/events.js +2 -0
- package/chaintypes/substrate/index.d.ts +22 -0
- package/chaintypes/substrate/index.js +2 -0
- package/chaintypes/substrate/json-rpc.d.ts +3 -0
- package/chaintypes/substrate/json-rpc.js +2 -0
- package/chaintypes/substrate/query.d.ts +3829 -0
- package/chaintypes/substrate/query.js +2 -0
- package/chaintypes/substrate/runtime.d.ts +850 -0
- package/chaintypes/substrate/runtime.js +2 -0
- package/chaintypes/substrate/tx.d.ts +14269 -0
- package/chaintypes/substrate/tx.js +2 -0
- package/chaintypes/substrate/types.d.ts +30457 -0
- package/chaintypes/substrate/types.js +2 -0
- package/cjs/chaintypes/index.js +17 -0
- package/cjs/chaintypes/substrate/consts.js +3 -0
- package/cjs/chaintypes/substrate/errors.js +3 -0
- package/cjs/chaintypes/substrate/events.js +3 -0
- package/cjs/chaintypes/substrate/index.js +18 -0
- package/cjs/chaintypes/substrate/json-rpc.js +3 -0
- package/cjs/chaintypes/substrate/query.js +3 -0
- package/cjs/chaintypes/substrate/runtime.js +3 -0
- package/cjs/chaintypes/substrate/tx.js +3 -0
- package/cjs/chaintypes/substrate/types.js +3 -0
- package/cjs/client/BaseSubstrateClient.js +257 -0
- package/cjs/client/Dedot.js +250 -0
- package/cjs/client/DedotClient.js +186 -0
- package/cjs/client/index.js +18 -0
- package/cjs/executor/ConstantExecutor.js +20 -0
- package/cjs/executor/ErrorExecutor.js +46 -0
- package/cjs/executor/EventExecutor.js +52 -0
- package/cjs/executor/Executor.js +42 -0
- package/cjs/executor/RuntimeApiExecutor.js +121 -0
- package/cjs/executor/StorageQueryExecutor.js +115 -0
- package/cjs/executor/TxExecutor.js +55 -0
- package/cjs/executor/index.js +26 -0
- package/cjs/executor/v2/RuntimeApiExecutorV2.js +21 -0
- package/cjs/executor/v2/StorageQueryExecutorV2.js +65 -0
- package/cjs/executor/v2/TxExecutorV2.js +20 -0
- package/cjs/extrinsic/extensions/ExtraSignedExtension.js +87 -0
- package/cjs/extrinsic/extensions/SignedExtension.js +41 -0
- package/cjs/extrinsic/extensions/index.js +19 -0
- package/cjs/extrinsic/extensions/known/ChargeAssetTxPayment.js +43 -0
- package/cjs/extrinsic/extensions/known/ChargeTransactionPayment.js +16 -0
- package/cjs/extrinsic/extensions/known/CheckGenesis.js +19 -0
- package/cjs/extrinsic/extensions/known/CheckMortality.js +90 -0
- package/cjs/extrinsic/extensions/known/CheckNonZeroSender.js +10 -0
- package/cjs/extrinsic/extensions/known/CheckNonce.js +33 -0
- package/cjs/extrinsic/extensions/known/CheckSpecVersion.js +19 -0
- package/cjs/extrinsic/extensions/known/CheckTxVersion.js +19 -0
- package/cjs/extrinsic/extensions/known/CheckWeight.js +10 -0
- package/cjs/extrinsic/extensions/known/PrevalidateAttests.js +11 -0
- package/cjs/extrinsic/extensions/known/index.js +25 -0
- package/cjs/extrinsic/index.js +18 -0
- package/cjs/extrinsic/submittable/BaseSubmittableExtrinsic.js +70 -0
- package/cjs/extrinsic/submittable/SubmittableExtrinsic.js +47 -0
- package/cjs/extrinsic/submittable/SubmittableExtrinsicV2.js +204 -0
- package/cjs/extrinsic/submittable/SubmittableResult.js +33 -0
- package/cjs/extrinsic/submittable/errors.js +16 -0
- package/cjs/extrinsic/submittable/fakeSigner.js +13 -0
- package/cjs/extrinsic/submittable/index.js +20 -0
- package/cjs/extrinsic/submittable/utils.js +20 -0
- package/cjs/index.js +21 -0
- package/cjs/json-rpc/JsonRpcClient.js +165 -0
- package/cjs/json-rpc/group/ChainHead/BlockUsage.js +24 -0
- package/cjs/json-rpc/group/ChainHead/ChainHead.js +603 -0
- package/cjs/json-rpc/group/ChainHead/error.js +59 -0
- package/cjs/json-rpc/group/ChainHead/index.js +18 -0
- package/cjs/json-rpc/group/ChainSpec.js +19 -0
- package/cjs/json-rpc/group/JsonRpcGroup.js +89 -0
- package/cjs/json-rpc/group/Transaction.js +25 -0
- package/cjs/json-rpc/group/TransactionWatch.js +17 -0
- package/cjs/json-rpc/group/index.js +21 -0
- package/cjs/json-rpc/index.js +20 -0
- package/cjs/json-rpc/scaledResponses.js +15 -0
- package/cjs/json-rpc/subscriptionsInfo.js +20 -0
- package/cjs/package.json +1 -0
- package/cjs/proxychain.js +27 -0
- package/cjs/storage/QueryableStorage.js +161 -0
- package/cjs/storage/index.js +17 -0
- package/cjs/types.js +2 -0
- package/client/BaseSubstrateClient.d.ts +65 -0
- package/client/BaseSubstrateClient.js +252 -0
- package/client/Dedot.d.ts +131 -0
- package/client/Dedot.js +246 -0
- package/client/DedotClient.d.ts +61 -0
- package/client/DedotClient.js +182 -0
- package/client/index.d.ts +2 -0
- package/client/index.js +2 -0
- package/executor/ConstantExecutor.d.ts +10 -0
- package/executor/ConstantExecutor.js +16 -0
- package/executor/ErrorExecutor.d.ts +10 -0
- package/executor/ErrorExecutor.js +42 -0
- package/executor/EventExecutor.d.ts +10 -0
- package/executor/EventExecutor.js +48 -0
- package/executor/Executor.d.ts +149 -0
- package/executor/Executor.js +38 -0
- package/executor/RuntimeApiExecutor.d.ts +27 -0
- package/executor/RuntimeApiExecutor.js +117 -0
- package/executor/StorageQueryExecutor.d.ts +14 -0
- package/executor/StorageQueryExecutor.js +111 -0
- package/executor/TxExecutor.d.ts +10 -0
- package/executor/TxExecutor.js +51 -0
- package/executor/index.d.ts +10 -0
- package/executor/index.js +10 -0
- package/executor/v2/RuntimeApiExecutorV2.d.ts +14 -0
- package/executor/v2/RuntimeApiExecutorV2.js +17 -0
- package/executor/v2/StorageQueryExecutorV2.d.ts +17 -0
- package/executor/v2/StorageQueryExecutorV2.js +61 -0
- package/executor/v2/TxExecutorV2.d.ts +11 -0
- package/executor/v2/TxExecutorV2.js +16 -0
- package/extrinsic/extensions/ExtraSignedExtension.d.ts +14 -0
- package/extrinsic/extensions/ExtraSignedExtension.js +60 -0
- package/extrinsic/extensions/SignedExtension.d.ts +40 -0
- package/extrinsic/extensions/SignedExtension.js +37 -0
- package/extrinsic/extensions/index.d.ts +3 -0
- package/extrinsic/extensions/index.js +3 -0
- package/extrinsic/extensions/known/ChargeAssetTxPayment.d.ts +14 -0
- package/extrinsic/extensions/known/ChargeAssetTxPayment.js +39 -0
- package/extrinsic/extensions/known/ChargeTransactionPayment.d.ts +6 -0
- package/extrinsic/extensions/known/ChargeTransactionPayment.js +12 -0
- package/extrinsic/extensions/known/CheckGenesis.d.ts +10 -0
- package/extrinsic/extensions/known/CheckGenesis.js +15 -0
- package/extrinsic/extensions/known/CheckMortality.d.ts +15 -0
- package/extrinsic/extensions/known/CheckMortality.js +86 -0
- package/extrinsic/extensions/known/CheckNonZeroSender.d.ts +6 -0
- package/extrinsic/extensions/known/CheckNonZeroSender.js +6 -0
- package/extrinsic/extensions/known/CheckNonce.d.ts +10 -0
- package/extrinsic/extensions/known/CheckNonce.js +29 -0
- package/extrinsic/extensions/known/CheckSpecVersion.d.ts +9 -0
- package/extrinsic/extensions/known/CheckSpecVersion.js +15 -0
- package/extrinsic/extensions/known/CheckTxVersion.d.ts +9 -0
- package/extrinsic/extensions/known/CheckTxVersion.js +15 -0
- package/extrinsic/extensions/known/CheckWeight.d.ts +6 -0
- package/extrinsic/extensions/known/CheckWeight.js +6 -0
- package/extrinsic/extensions/known/PrevalidateAttests.d.ts +7 -0
- package/extrinsic/extensions/known/PrevalidateAttests.js +7 -0
- package/extrinsic/extensions/known/index.d.ts +3 -0
- package/extrinsic/extensions/known/index.js +22 -0
- package/extrinsic/index.d.ts +2 -0
- package/extrinsic/index.js +2 -0
- package/extrinsic/submittable/BaseSubmittableExtrinsic.d.ts +17 -0
- package/extrinsic/submittable/BaseSubmittableExtrinsic.js +66 -0
- package/extrinsic/submittable/SubmittableExtrinsic.d.ts +12 -0
- package/extrinsic/submittable/SubmittableExtrinsic.js +43 -0
- package/extrinsic/submittable/SubmittableExtrinsicV2.d.ts +15 -0
- package/extrinsic/submittable/SubmittableExtrinsicV2.js +200 -0
- package/extrinsic/submittable/SubmittableResult.d.ts +19 -0
- package/extrinsic/submittable/SubmittableResult.js +29 -0
- package/extrinsic/submittable/errors.d.ts +11 -0
- package/extrinsic/submittable/errors.js +12 -0
- package/extrinsic/submittable/fakeSigner.d.ts +2 -0
- package/extrinsic/submittable/fakeSigner.js +10 -0
- package/extrinsic/submittable/index.d.ts +4 -0
- package/extrinsic/submittable/index.js +4 -0
- package/extrinsic/submittable/utils.d.ts +10 -0
- package/extrinsic/submittable/utils.js +15 -0
- package/index.d.ts +6 -0
- package/index.js +5 -0
- package/json-rpc/JsonRpcClient.d.ts +50 -0
- package/json-rpc/JsonRpcClient.js +160 -0
- package/json-rpc/group/ChainHead/BlockUsage.d.ts +11 -0
- package/json-rpc/group/ChainHead/BlockUsage.js +20 -0
- package/json-rpc/group/ChainHead/ChainHead.d.ts +70 -0
- package/json-rpc/group/ChainHead/ChainHead.js +599 -0
- package/json-rpc/group/ChainHead/error.d.ts +47 -0
- package/json-rpc/group/ChainHead/error.js +48 -0
- package/json-rpc/group/ChainHead/index.d.ts +2 -0
- package/json-rpc/group/ChainHead/index.js +2 -0
- package/json-rpc/group/ChainSpec.d.ts +10 -0
- package/json-rpc/group/ChainSpec.js +15 -0
- package/json-rpc/group/JsonRpcGroup.d.ts +74 -0
- package/json-rpc/group/JsonRpcGroup.js +85 -0
- package/json-rpc/group/Transaction.d.ts +11 -0
- package/json-rpc/group/Transaction.js +21 -0
- package/json-rpc/group/TransactionWatch.d.ts +10 -0
- package/json-rpc/group/TransactionWatch.js +13 -0
- package/json-rpc/group/index.d.ts +5 -0
- package/json-rpc/group/index.js +5 -0
- package/json-rpc/index.d.ts +4 -0
- package/json-rpc/index.js +4 -0
- package/json-rpc/scaledResponses.d.ts +2 -0
- package/json-rpc/scaledResponses.js +12 -0
- package/json-rpc/subscriptionsInfo.d.ts +2 -0
- package/json-rpc/subscriptionsInfo.js +17 -0
- package/package.json +54 -0
- package/proxychain.d.ts +14 -0
- package/proxychain.js +23 -0
- package/storage/QueryableStorage.d.ts +35 -0
- package/storage/QueryableStorage.js +157 -0
- package/storage/index.d.ts +1 -0
- package/storage/index.js +1 -0
- package/types.d.ts +120 -0
- package/types.js +1 -0
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
import { $Header } from '@dedot/codecs';
|
|
2
|
+
import { assert, AsyncQueue, deferred, ensurePresence, noop, waitFor } from '@dedot/utils';
|
|
3
|
+
import { JsonRpcGroup } from '../JsonRpcGroup.js';
|
|
4
|
+
import { BlockUsage } from './BlockUsage.js';
|
|
5
|
+
import { ChainHeadBlockNotPinnedError, ChainHeadBlockPrunedError, ChainHeadError, ChainHeadLimitReachedError, ChainHeadOperationError, ChainHeadOperationInaccessibleError, ChainHeadStopError, RetryStrategy, } from './error.js';
|
|
6
|
+
export const MIN_FINALIZED_QUEUE_SIZE = 10; // finalized queue size
|
|
7
|
+
export class ChainHead extends JsonRpcGroup {
|
|
8
|
+
#unsub;
|
|
9
|
+
#subscriptionId;
|
|
10
|
+
#handlers;
|
|
11
|
+
#pendingOperations;
|
|
12
|
+
#finalizedQueue;
|
|
13
|
+
#pinnedBlocks;
|
|
14
|
+
#bestHash;
|
|
15
|
+
#finalizedHash; // best finalized hash
|
|
16
|
+
#finalizedRuntime;
|
|
17
|
+
#followResponseQueue;
|
|
18
|
+
#retryQueue;
|
|
19
|
+
#recovering;
|
|
20
|
+
#blockUsage;
|
|
21
|
+
#cache;
|
|
22
|
+
constructor(client, options) {
|
|
23
|
+
super(client, { prefix: 'chainHead', supportedVersions: ['unstable', 'v1'], ...options });
|
|
24
|
+
this.#handlers = {};
|
|
25
|
+
this.#pendingOperations = {};
|
|
26
|
+
this.#pinnedBlocks = {};
|
|
27
|
+
this.#finalizedQueue = [];
|
|
28
|
+
this.#followResponseQueue = new AsyncQueue();
|
|
29
|
+
this.#retryQueue = new AsyncQueue();
|
|
30
|
+
this.#blockUsage = new BlockUsage();
|
|
31
|
+
this.#cache = new Map();
|
|
32
|
+
}
|
|
33
|
+
async runtimeVersion() {
|
|
34
|
+
await this.#ensureFollowed();
|
|
35
|
+
return this.#finalizedRuntime;
|
|
36
|
+
}
|
|
37
|
+
async bestRuntimeVersion() {
|
|
38
|
+
await this.#ensureFollowed();
|
|
39
|
+
return this.#findRuntimeAt(this.#bestHash) || this.runtimeVersion();
|
|
40
|
+
}
|
|
41
|
+
async finalizedHash() {
|
|
42
|
+
await this.#ensureFollowed();
|
|
43
|
+
return this.#finalizedHash;
|
|
44
|
+
}
|
|
45
|
+
async bestHash() {
|
|
46
|
+
await this.#ensureFollowed();
|
|
47
|
+
return this.#bestHash;
|
|
48
|
+
}
|
|
49
|
+
async bestBlock() {
|
|
50
|
+
return this.findBlock(await this.bestHash());
|
|
51
|
+
}
|
|
52
|
+
async finalizedBlock() {
|
|
53
|
+
return this.findBlock(await this.finalizedHash());
|
|
54
|
+
}
|
|
55
|
+
findBlock(hash) {
|
|
56
|
+
return this.#pinnedBlocks[hash];
|
|
57
|
+
}
|
|
58
|
+
isPinned(hash) {
|
|
59
|
+
return !!this.findBlock(hash);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* chainHead_unfollow
|
|
63
|
+
*/
|
|
64
|
+
async unfollow() {
|
|
65
|
+
await this.#ensureFollowed();
|
|
66
|
+
this.#unsub && (await this.#unsub());
|
|
67
|
+
this.#cleanUp();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* chainHead_follow
|
|
71
|
+
*/
|
|
72
|
+
async follow() {
|
|
73
|
+
assert(!this.#subscriptionId, 'Already followed chain head. Please unfollow first.');
|
|
74
|
+
return this.#doFollow();
|
|
75
|
+
}
|
|
76
|
+
async #doFollow() {
|
|
77
|
+
const defer = deferred();
|
|
78
|
+
try {
|
|
79
|
+
this.#unsub && this.#unsub().catch(noop); // ensure unfollowed
|
|
80
|
+
this.#unsub = await this.send('follow', true, (event, subscription) => {
|
|
81
|
+
this.#followResponseQueue
|
|
82
|
+
.enqueue(async () => {
|
|
83
|
+
await this.#onFollowEvent(event, subscription);
|
|
84
|
+
if (event.event == 'initialized') {
|
|
85
|
+
defer.resolve();
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
.catch(console.error); // print this out for logging purpose
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
defer.reject(e);
|
|
93
|
+
}
|
|
94
|
+
return defer.promise;
|
|
95
|
+
}
|
|
96
|
+
#onFollowEvent = async (result, subscription) => {
|
|
97
|
+
switch (result.event) {
|
|
98
|
+
case 'initialized': {
|
|
99
|
+
const { finalizedBlockHashes = [], finalizedBlockHash, finalizedBlockRuntime } = result;
|
|
100
|
+
if (finalizedBlockHash)
|
|
101
|
+
finalizedBlockHashes.push(finalizedBlockHash);
|
|
102
|
+
this.#subscriptionId = subscription.subscriptionId;
|
|
103
|
+
this.#finalizedQueue = finalizedBlockHashes;
|
|
104
|
+
this.#finalizedRuntime = this.#extractRuntime(finalizedBlockRuntime);
|
|
105
|
+
assert(this.#finalizedRuntime, 'Invalid finalized runtime');
|
|
106
|
+
this.#bestHash = this.#finalizedHash = finalizedBlockHashes.at(-1);
|
|
107
|
+
this.#pinnedBlocks = finalizedBlockHashes.reduce((o, hash, idx, arr) => {
|
|
108
|
+
o[hash] = { hash, parent: arr[idx - 1], number: idx };
|
|
109
|
+
// assign finalized runtime to the current finalized block
|
|
110
|
+
if (idx === finalizedBlockHashes.length - 1) {
|
|
111
|
+
o[hash]['runtime'] = this.#finalizedRuntime;
|
|
112
|
+
}
|
|
113
|
+
return o;
|
|
114
|
+
}, {});
|
|
115
|
+
const header = $Header.tryDecode(await this.#getHeader(finalizedBlockHashes[0]));
|
|
116
|
+
Object.values(this.#pinnedBlocks).forEach((b, idx) => {
|
|
117
|
+
b.number += header.number;
|
|
118
|
+
if (idx === 0) {
|
|
119
|
+
b.parent = header.parentHash;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case 'newBlock': {
|
|
125
|
+
const { blockHash: hash, parentBlockHash: parent, newRuntime } = result;
|
|
126
|
+
const runtime = this.#extractRuntime(newRuntime);
|
|
127
|
+
const parentBlock = this.findBlock(parent);
|
|
128
|
+
assert(parentBlock, `Parent block not found for new block ${hash}`);
|
|
129
|
+
this.#pinnedBlocks[hash] = {
|
|
130
|
+
hash,
|
|
131
|
+
parent,
|
|
132
|
+
// if the runtime is not provided, we'll find it from the parent block
|
|
133
|
+
runtime: runtime || this.#findRuntimeAt(parent),
|
|
134
|
+
number: parentBlock.number + 1,
|
|
135
|
+
};
|
|
136
|
+
this.emit('newBlock', this.#pinnedBlocks[hash]);
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case 'bestBlockChanged': {
|
|
140
|
+
const { bestBlockHash } = result;
|
|
141
|
+
const currentBestBlock = this.findBlock(this.#bestHash);
|
|
142
|
+
const newBestBlock = this.findBlock(bestBlockHash);
|
|
143
|
+
if (!newBestBlock)
|
|
144
|
+
return;
|
|
145
|
+
if (currentBestBlock.hash === newBestBlock.hash)
|
|
146
|
+
return;
|
|
147
|
+
const bestChainChanged = !this.#onTheSameChain(currentBestBlock, newBestBlock);
|
|
148
|
+
this.#bestHash = bestBlockHash;
|
|
149
|
+
this.emit('bestBlock', newBestBlock, bestChainChanged);
|
|
150
|
+
if (bestChainChanged)
|
|
151
|
+
this.emit('bestChainChanged', newBestBlock);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case 'finalized': {
|
|
155
|
+
const { finalizedBlockHashes, prunedBlockHashes } = result;
|
|
156
|
+
this.#finalizedHash = finalizedBlockHashes.at(-1);
|
|
157
|
+
const finalizedRuntime = this.#findRuntimeAt(this.#finalizedHash);
|
|
158
|
+
if (finalizedRuntime) {
|
|
159
|
+
this.#finalizedRuntime = finalizedRuntime;
|
|
160
|
+
}
|
|
161
|
+
// push new finalized hashes into the queue, we'll adjust the size later if needed
|
|
162
|
+
finalizedBlockHashes.forEach((hash) => {
|
|
163
|
+
if (this.#finalizedQueue.includes(hash))
|
|
164
|
+
return;
|
|
165
|
+
this.#finalizedQueue.push(hash);
|
|
166
|
+
});
|
|
167
|
+
this.emit('finalizedBlock', this.findBlock(this.#finalizedHash));
|
|
168
|
+
// TODO should we find all descendants of the pruned blocks and unpin them as well?
|
|
169
|
+
// that's probably a premature optimization
|
|
170
|
+
const finalizedBlockHeights = finalizedBlockHashes.map((hash) => this.findBlock(hash).number);
|
|
171
|
+
const pinnedHashes = Object.keys(this.#pinnedBlocks);
|
|
172
|
+
const hashesToUnpin = new Set([
|
|
173
|
+
...prunedBlockHashes.filter((hash) => pinnedHashes.includes(hash)),
|
|
174
|
+
// Since we have the current finalized blocks,
|
|
175
|
+
// we can mark all the other blocks at the same height as pruned and unpin all together with the reported pruned blocks
|
|
176
|
+
...Object.values(this.#pinnedBlocks)
|
|
177
|
+
.filter((b) => finalizedBlockHeights.includes(b.number))
|
|
178
|
+
.filter((b) => !finalizedBlockHashes.includes(b.hash))
|
|
179
|
+
.map((b) => b.hash),
|
|
180
|
+
]);
|
|
181
|
+
// TODO account for operations that haven't received its operationId yet
|
|
182
|
+
Object.values(this.#handlers).forEach(({ defer, hash, operationId }) => {
|
|
183
|
+
if (hashesToUnpin.has(hash)) {
|
|
184
|
+
defer.reject(new ChainHeadBlockPrunedError());
|
|
185
|
+
this.stopOperation(operationId).catch(noop);
|
|
186
|
+
delete this.#handlers[operationId];
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
// Unpin the oldest finalized pinned blocks to maintain the queue size
|
|
190
|
+
if (this.#finalizedQueue.length > MIN_FINALIZED_QUEUE_SIZE) {
|
|
191
|
+
const finalizedQueue = this.#finalizedQueue.slice();
|
|
192
|
+
const numOfItemsToUnpin = finalizedQueue.length - MIN_FINALIZED_QUEUE_SIZE;
|
|
193
|
+
const queuedHashesToUnpin = finalizedQueue.splice(0, numOfItemsToUnpin);
|
|
194
|
+
queuedHashesToUnpin.forEach((hash) => {
|
|
195
|
+
// if the block is being used, we'll keep it pinned
|
|
196
|
+
// and recheck it later in the next finalized event
|
|
197
|
+
if (this.#blockUsage.usage(hash) > 0) {
|
|
198
|
+
finalizedQueue.unshift(hash);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
hashesToUnpin.add(hash);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
this.#finalizedQueue = finalizedQueue;
|
|
205
|
+
}
|
|
206
|
+
hashesToUnpin.forEach((hash) => {
|
|
207
|
+
if (!this.isPinned(hash))
|
|
208
|
+
return;
|
|
209
|
+
delete this.#pinnedBlocks[hash];
|
|
210
|
+
// clear cache
|
|
211
|
+
Array.from(this.#cache.keys())
|
|
212
|
+
.filter((key) => key.startsWith(`${hash}::`))
|
|
213
|
+
.forEach((key) => this.#cache.delete(key));
|
|
214
|
+
});
|
|
215
|
+
this.unpin([...hashesToUnpin]).catch(noop);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case 'stop': {
|
|
219
|
+
// 1. First thing, set up the #recovering promise
|
|
220
|
+
// So any requests/operations coming to the chainHead should be put on waiting
|
|
221
|
+
// for the #recovering promise to resolve
|
|
222
|
+
this.#recovering = deferred();
|
|
223
|
+
// 2. Attempt to re-follow the chainHead
|
|
224
|
+
this.#doFollow()
|
|
225
|
+
.then(() => {
|
|
226
|
+
// 3. Resolve the recovering promise
|
|
227
|
+
// This means to continue all pending requests while the chainHead started recovering mode at step 1.
|
|
228
|
+
this.#recovering.resolve();
|
|
229
|
+
// 4. Recover stale operations
|
|
230
|
+
// 4.1. Operations that's going on & waiting to receiving its operationId
|
|
231
|
+
// will eventually get an `limitedReached` error for using a stale followSubscriptionId
|
|
232
|
+
// these operation will automatically be recovered via the #retryQueue
|
|
233
|
+
// after the chainHead is re-followed & the #recovering promise is resolved
|
|
234
|
+
// 4.2. Operations that's already received an operationId, is waiting for its response
|
|
235
|
+
// will not receive any data, we'll throw a ChainHeadStopError to trigger retrying via the #retryQueue
|
|
236
|
+
Object.values(this.#handlers).forEach(({ defer, operationId }) => {
|
|
237
|
+
defer.reject(new ChainHeadStopError('ChainHead subscription stopped!'));
|
|
238
|
+
delete this.#handlers[operationId];
|
|
239
|
+
});
|
|
240
|
+
})
|
|
241
|
+
.catch((e) => {
|
|
242
|
+
console.error(e);
|
|
243
|
+
// TODO we should retry a few attempts
|
|
244
|
+
this.#recovering.reject(new ChainHeadError('Cannot recover from stop event!'));
|
|
245
|
+
Object.values(this.#handlers).forEach(({ defer, operationId }) => {
|
|
246
|
+
defer.reject(new ChainHeadError('Cannot recover from stop event!'));
|
|
247
|
+
delete this.#handlers[operationId];
|
|
248
|
+
});
|
|
249
|
+
})
|
|
250
|
+
.finally(() => {
|
|
251
|
+
// cleaning up
|
|
252
|
+
waitFor().then(() => {
|
|
253
|
+
this.#recovering = undefined;
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
case 'operationBodyDone': {
|
|
259
|
+
this.#handleOperationResponse(result, ({ defer }) => {
|
|
260
|
+
defer.resolve(result.value);
|
|
261
|
+
});
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
case 'operationCallDone': {
|
|
265
|
+
this.#handleOperationResponse(result, ({ defer }) => {
|
|
266
|
+
defer.resolve(result.output);
|
|
267
|
+
});
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
case 'operationStorageItems': {
|
|
271
|
+
this.#handleOperationResponse(result, (handler) => {
|
|
272
|
+
if (!handler.storageResults)
|
|
273
|
+
handler.storageResults = [];
|
|
274
|
+
handler.storageResults.push(...result.items);
|
|
275
|
+
}, false);
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case 'operationStorageDone': {
|
|
279
|
+
this.#handleOperationResponse(result, ({ defer, storageResults }) => {
|
|
280
|
+
defer.resolve(storageResults || []);
|
|
281
|
+
});
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
case 'operationError': {
|
|
285
|
+
this.#handleOperationResponse(result, ({ defer }) => {
|
|
286
|
+
defer.reject(new ChainHeadOperationError(result.error));
|
|
287
|
+
});
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case 'operationInaccessible': {
|
|
291
|
+
this.#handleOperationResponse(result, ({ defer }) => {
|
|
292
|
+
defer.reject(new ChainHeadOperationInaccessibleError('Operation Inaccessible'));
|
|
293
|
+
});
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
case 'operationWaitingForContinue': {
|
|
297
|
+
this.continue(result.operationId).catch(noop);
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
#findRuntimeAt(at) {
|
|
303
|
+
const block = this.findBlock(at);
|
|
304
|
+
if (!block)
|
|
305
|
+
return undefined;
|
|
306
|
+
const runtime = block.runtime;
|
|
307
|
+
if (runtime)
|
|
308
|
+
return runtime;
|
|
309
|
+
if (this.#finalizedQueue.includes(at))
|
|
310
|
+
return;
|
|
311
|
+
return this.#findRuntimeAt(block.parent);
|
|
312
|
+
}
|
|
313
|
+
#onTheSameChain(b1, b2) {
|
|
314
|
+
if (!b1 || !b2)
|
|
315
|
+
return false;
|
|
316
|
+
if (b1.number === b2.number) {
|
|
317
|
+
return b1.hash === b2.hash;
|
|
318
|
+
}
|
|
319
|
+
else if (b1.number < b2.number) {
|
|
320
|
+
return this.#onTheSameChain(b1, this.findBlock(b2.parent));
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
return this.#onTheSameChain(this.findBlock(b1.parent), b2);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
#ensurePinnedHash(hash) {
|
|
327
|
+
if (hash) {
|
|
328
|
+
if (this.isPinned(hash)) {
|
|
329
|
+
return hash;
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
throw new ChainHeadBlockNotPinnedError(`Block hash ${hash} is not pinned`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return ensurePresence(this.#bestHash || this.#finalizedHash);
|
|
336
|
+
}
|
|
337
|
+
#getOperationHandler(result) {
|
|
338
|
+
const handler = this.#handlers[result.operationId];
|
|
339
|
+
if (handler)
|
|
340
|
+
return handler;
|
|
341
|
+
// Register pending operations
|
|
342
|
+
if (!this.#pendingOperations[result.operationId]) {
|
|
343
|
+
this.#pendingOperations[result.operationId] = [];
|
|
344
|
+
}
|
|
345
|
+
this.#pendingOperations[result.operationId].push(result);
|
|
346
|
+
}
|
|
347
|
+
#handleOperationResponse(result, handle, cleanUp = true) {
|
|
348
|
+
const handler = this.#getOperationHandler(result);
|
|
349
|
+
if (!handler)
|
|
350
|
+
return;
|
|
351
|
+
handle(handler);
|
|
352
|
+
if (cleanUp) {
|
|
353
|
+
this.#cleanUpOperation(result.operationId);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
#extractRuntime(runtimeEvent) {
|
|
357
|
+
if (!runtimeEvent)
|
|
358
|
+
return;
|
|
359
|
+
if (runtimeEvent.type == 'valid') {
|
|
360
|
+
return runtimeEvent.spec;
|
|
361
|
+
}
|
|
362
|
+
// If the runtime is invalid,
|
|
363
|
+
// we safely return an undefined runtime for now
|
|
364
|
+
console.error(runtimeEvent.error);
|
|
365
|
+
}
|
|
366
|
+
#cleanUp() {
|
|
367
|
+
this.off('newBlock');
|
|
368
|
+
this.off('bestBlock');
|
|
369
|
+
this.off('finalizedBlock');
|
|
370
|
+
this.#subscriptionId = undefined;
|
|
371
|
+
this.#unsub = undefined;
|
|
372
|
+
this.#handlers = {};
|
|
373
|
+
this.#pendingOperations = {};
|
|
374
|
+
this.#pinnedBlocks = {};
|
|
375
|
+
this.#bestHash = undefined;
|
|
376
|
+
this.#finalizedHash = undefined;
|
|
377
|
+
this.#finalizedRuntime = undefined;
|
|
378
|
+
this.#followResponseQueue.clear();
|
|
379
|
+
this.#retryQueue.clear();
|
|
380
|
+
this.#blockUsage.clear();
|
|
381
|
+
this.#cache.clear();
|
|
382
|
+
}
|
|
383
|
+
async #ensureFollowed() {
|
|
384
|
+
if (this.#recovering) {
|
|
385
|
+
await this.#recovering.promise;
|
|
386
|
+
}
|
|
387
|
+
assert(this.#subscriptionId, 'Please call the .follow() method before invoking any other methods in this group.');
|
|
388
|
+
}
|
|
389
|
+
#cleanUpOperation(operationId) {
|
|
390
|
+
delete this.#handlers[operationId];
|
|
391
|
+
this.stopOperation(operationId).catch(noop);
|
|
392
|
+
}
|
|
393
|
+
async #performOperationWithRetry(operation, hash) {
|
|
394
|
+
try {
|
|
395
|
+
this.#blockUsage.use(hash);
|
|
396
|
+
return await operation();
|
|
397
|
+
}
|
|
398
|
+
catch (e) {
|
|
399
|
+
if (e instanceof ChainHeadError && e.retryStrategy) {
|
|
400
|
+
return this.#retryOperation(e.retryStrategy, operation);
|
|
401
|
+
}
|
|
402
|
+
throw e;
|
|
403
|
+
}
|
|
404
|
+
finally {
|
|
405
|
+
this.#blockUsage.release(hash);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async #retryOperation(strategy, retry) {
|
|
409
|
+
try {
|
|
410
|
+
return await new Promise((resolve, reject) => {
|
|
411
|
+
setTimeout(() => {
|
|
412
|
+
if (strategy === RetryStrategy.NOW) {
|
|
413
|
+
retry().then(resolve).catch(reject);
|
|
414
|
+
}
|
|
415
|
+
else if (strategy === RetryStrategy.QUEUED) {
|
|
416
|
+
this.#retryQueue.enqueue(retry).then(resolve).catch(reject);
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
throw new Error('Invalid retry strategy');
|
|
420
|
+
}
|
|
421
|
+
}); // retry again in the next tick
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
catch (e) {
|
|
425
|
+
// retry again until success, TODO we might need to limit the number of retries
|
|
426
|
+
if (e instanceof ChainHeadError && e.retryStrategy) {
|
|
427
|
+
return this.#retryOperation(e.retryStrategy, retry);
|
|
428
|
+
}
|
|
429
|
+
throw e;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
#awaitOperation(resp, hash) {
|
|
433
|
+
if (resp.result === 'limitReached') {
|
|
434
|
+
throw new ChainHeadLimitReachedError('Limit reached');
|
|
435
|
+
}
|
|
436
|
+
const defer = deferred();
|
|
437
|
+
this.#handlers[resp.operationId] = {
|
|
438
|
+
operationId: resp.operationId,
|
|
439
|
+
defer,
|
|
440
|
+
hash,
|
|
441
|
+
};
|
|
442
|
+
// Resolve pending operations
|
|
443
|
+
if (this.#pendingOperations[resp.operationId]) {
|
|
444
|
+
this.#pendingOperations[resp.operationId].forEach((one) => {
|
|
445
|
+
this.#onFollowEvent(one);
|
|
446
|
+
});
|
|
447
|
+
delete this.#pendingOperations[resp.operationId];
|
|
448
|
+
}
|
|
449
|
+
return defer.promise;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* chainHead_body
|
|
453
|
+
*/
|
|
454
|
+
async body(at) {
|
|
455
|
+
await this.#ensureFollowed();
|
|
456
|
+
const shouldRetryOnPrunedBlock = !at;
|
|
457
|
+
try {
|
|
458
|
+
const atHash = this.#ensurePinnedHash(at);
|
|
459
|
+
const cacheKey = `${atHash}::body`;
|
|
460
|
+
if (this.#cache.has(cacheKey)) {
|
|
461
|
+
return this.#cache.get(cacheKey);
|
|
462
|
+
}
|
|
463
|
+
const operation = async () => {
|
|
464
|
+
await this.#ensureFollowed();
|
|
465
|
+
const hash = this.#ensurePinnedHash(atHash);
|
|
466
|
+
const resp = await this.send('body', this.#subscriptionId, hash);
|
|
467
|
+
return this.#awaitOperation(resp, hash);
|
|
468
|
+
};
|
|
469
|
+
const resp = await this.#performOperationWithRetry(operation, atHash);
|
|
470
|
+
this.#cache.set(cacheKey, resp);
|
|
471
|
+
return resp;
|
|
472
|
+
}
|
|
473
|
+
catch (e) {
|
|
474
|
+
if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
|
|
475
|
+
return this.body();
|
|
476
|
+
}
|
|
477
|
+
throw e;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* chainHead_call
|
|
482
|
+
*/
|
|
483
|
+
async call(func, params = '0x', at) {
|
|
484
|
+
await this.#ensureFollowed();
|
|
485
|
+
const shouldRetryOnPrunedBlock = !at;
|
|
486
|
+
try {
|
|
487
|
+
const atHash = this.#ensurePinnedHash(at);
|
|
488
|
+
const cacheKey = `${atHash}::call::${func}::${params}`;
|
|
489
|
+
if (this.#cache.has(cacheKey)) {
|
|
490
|
+
return this.#cache.get(cacheKey);
|
|
491
|
+
}
|
|
492
|
+
const operation = async () => {
|
|
493
|
+
await this.#ensureFollowed();
|
|
494
|
+
const hash = this.#ensurePinnedHash(atHash);
|
|
495
|
+
const resp = await this.send('call', this.#subscriptionId, hash, func, params);
|
|
496
|
+
return this.#awaitOperation(resp, hash);
|
|
497
|
+
};
|
|
498
|
+
const resp = await this.#performOperationWithRetry(operation, atHash);
|
|
499
|
+
this.#cache.set(cacheKey, resp);
|
|
500
|
+
return resp;
|
|
501
|
+
}
|
|
502
|
+
catch (e) {
|
|
503
|
+
if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
|
|
504
|
+
return this.call(func, params);
|
|
505
|
+
}
|
|
506
|
+
throw e;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* chainHead_header
|
|
511
|
+
*/
|
|
512
|
+
async header(at) {
|
|
513
|
+
await this.#ensureFollowed();
|
|
514
|
+
const hash = this.#ensurePinnedHash(at);
|
|
515
|
+
const cacheKey = `${hash}::header`;
|
|
516
|
+
if (this.#cache.has(cacheKey)) {
|
|
517
|
+
return this.#cache.get(cacheKey);
|
|
518
|
+
}
|
|
519
|
+
const resp = await this.#getHeader(hash);
|
|
520
|
+
this.#cache.set(cacheKey, resp);
|
|
521
|
+
return resp;
|
|
522
|
+
}
|
|
523
|
+
async #getHeader(at) {
|
|
524
|
+
return await this.send('header', this.#subscriptionId, at);
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* chainHead_storage
|
|
528
|
+
*/
|
|
529
|
+
async storage(items, childTrie, at) {
|
|
530
|
+
await this.#ensureFollowed();
|
|
531
|
+
const shouldRetryOnPrunedBlock = !at;
|
|
532
|
+
const hash = this.#ensurePinnedHash(at);
|
|
533
|
+
try {
|
|
534
|
+
// JSON.stringify(items) might get big, we probably should do a twox hashing in such case
|
|
535
|
+
const cacheKey = `${hash}::storage::${JSON.stringify(items)}::${childTrie ?? null}`;
|
|
536
|
+
if (this.#cache.has(cacheKey)) {
|
|
537
|
+
return this.#cache.get(cacheKey);
|
|
538
|
+
}
|
|
539
|
+
this.#blockUsage.use(hash);
|
|
540
|
+
const results = [];
|
|
541
|
+
let queryItems = items;
|
|
542
|
+
while (queryItems.length > 0) {
|
|
543
|
+
const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
|
|
544
|
+
results.push(...newBatch);
|
|
545
|
+
queryItems = newDiscardedItems;
|
|
546
|
+
}
|
|
547
|
+
this.#cache.set(cacheKey, results);
|
|
548
|
+
return results;
|
|
549
|
+
}
|
|
550
|
+
catch (e) {
|
|
551
|
+
if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
|
|
552
|
+
return this.storage(items, childTrie);
|
|
553
|
+
}
|
|
554
|
+
throw e;
|
|
555
|
+
}
|
|
556
|
+
finally {
|
|
557
|
+
this.#blockUsage.release(hash);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
async #getStorage(items, childTrie, at) {
|
|
561
|
+
const operation = () => this.#getStorageOperation(items, childTrie, this.#ensurePinnedHash(at));
|
|
562
|
+
return this.#performOperationWithRetry(operation, at);
|
|
563
|
+
}
|
|
564
|
+
async #getStorageOperation(items, childTrie, at) {
|
|
565
|
+
await this.#ensureFollowed();
|
|
566
|
+
const resp = await this.send('storage', this.#subscriptionId, at, items, childTrie);
|
|
567
|
+
let discardedItems = [];
|
|
568
|
+
if (resp.result === 'started' && resp.discardedItems && resp.discardedItems > 0) {
|
|
569
|
+
discardedItems = items.slice(items.length - resp.discardedItems);
|
|
570
|
+
}
|
|
571
|
+
return [await this.#awaitOperation(resp, at), discardedItems];
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* chainHead_stopOperation
|
|
575
|
+
* @protected
|
|
576
|
+
*/
|
|
577
|
+
async stopOperation(operationId) {
|
|
578
|
+
await this.#ensureFollowed();
|
|
579
|
+
await this.send('stopOperation', this.#subscriptionId, operationId);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* chainHead_continue
|
|
583
|
+
* @protected
|
|
584
|
+
*/
|
|
585
|
+
async continue(operationId) {
|
|
586
|
+
await this.#ensureFollowed();
|
|
587
|
+
await this.send('continue', this.#subscriptionId, operationId);
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* chainHead_unpin
|
|
591
|
+
* @protected
|
|
592
|
+
*/
|
|
593
|
+
async unpin(hashes) {
|
|
594
|
+
await this.#ensureFollowed();
|
|
595
|
+
if (Array.isArray(hashes) && hashes.length === 0)
|
|
596
|
+
return;
|
|
597
|
+
await this.send('unpin', this.#subscriptionId, hashes);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { DedotError } from '@dedot/utils';
|
|
2
|
+
export declare enum RetryStrategy {
|
|
3
|
+
NOW = "NOW",// Retry immediately
|
|
4
|
+
QUEUED = "QUEUED"
|
|
5
|
+
}
|
|
6
|
+
export declare class ChainHeadError extends DedotError {
|
|
7
|
+
retryStrategy?: RetryStrategy | undefined;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Operation Inaccessible Error
|
|
11
|
+
*
|
|
12
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_follow.html#operationinaccessible
|
|
13
|
+
*/
|
|
14
|
+
export declare class ChainHeadOperationInaccessibleError extends ChainHeadError {
|
|
15
|
+
retryStrategy: RetryStrategy;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Stop Error
|
|
19
|
+
*
|
|
20
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_follow.html#stop
|
|
21
|
+
*/
|
|
22
|
+
export declare class ChainHeadStopError extends ChainHeadError {
|
|
23
|
+
retryStrategy: RetryStrategy;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Operation Error
|
|
27
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_follow.html#operationerror
|
|
28
|
+
*/
|
|
29
|
+
export declare class ChainHeadOperationError extends ChainHeadError {
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Limit Reached Error
|
|
33
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_storage.html#limitreached
|
|
34
|
+
*/
|
|
35
|
+
export declare class ChainHeadLimitReachedError extends ChainHeadError {
|
|
36
|
+
retryStrategy: RetryStrategy;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Invalid Runtime Error
|
|
40
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_storage.html#limitreached
|
|
41
|
+
*/
|
|
42
|
+
export declare class ChainHeadInvalidRuntimeError extends ChainHeadError {
|
|
43
|
+
}
|
|
44
|
+
export declare class ChainHeadBlockNotPinnedError extends ChainHeadError {
|
|
45
|
+
}
|
|
46
|
+
export declare class ChainHeadBlockPrunedError extends ChainHeadError {
|
|
47
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DedotError } from '@dedot/utils';
|
|
2
|
+
export var RetryStrategy;
|
|
3
|
+
(function (RetryStrategy) {
|
|
4
|
+
RetryStrategy["NOW"] = "NOW";
|
|
5
|
+
RetryStrategy["QUEUED"] = "QUEUED";
|
|
6
|
+
})(RetryStrategy || (RetryStrategy = {}));
|
|
7
|
+
export class ChainHeadError extends DedotError {
|
|
8
|
+
retryStrategy;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Operation Inaccessible Error
|
|
12
|
+
*
|
|
13
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_follow.html#operationinaccessible
|
|
14
|
+
*/
|
|
15
|
+
export class ChainHeadOperationInaccessibleError extends ChainHeadError {
|
|
16
|
+
retryStrategy = RetryStrategy.NOW;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Stop Error
|
|
20
|
+
*
|
|
21
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_follow.html#stop
|
|
22
|
+
*/
|
|
23
|
+
export class ChainHeadStopError extends ChainHeadError {
|
|
24
|
+
retryStrategy = RetryStrategy.QUEUED;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Operation Error
|
|
28
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_follow.html#operationerror
|
|
29
|
+
*/
|
|
30
|
+
export class ChainHeadOperationError extends ChainHeadError {
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Limit Reached Error
|
|
34
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_storage.html#limitreached
|
|
35
|
+
*/
|
|
36
|
+
export class ChainHeadLimitReachedError extends ChainHeadError {
|
|
37
|
+
retryStrategy = RetryStrategy.QUEUED;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Invalid Runtime Error
|
|
41
|
+
* Ref: https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_storage.html#limitreached
|
|
42
|
+
*/
|
|
43
|
+
export class ChainHeadInvalidRuntimeError extends ChainHeadError {
|
|
44
|
+
}
|
|
45
|
+
export class ChainHeadBlockNotPinnedError extends ChainHeadError {
|
|
46
|
+
}
|
|
47
|
+
export class ChainHeadBlockPrunedError extends ChainHeadError {
|
|
48
|
+
}
|