@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,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseSubmittableExtrinsic = void 0;
|
|
4
|
+
const codecs_1 = require("@dedot/codecs");
|
|
5
|
+
const utils_1 = require("@dedot/utils");
|
|
6
|
+
const index_js_1 = require("../extensions/index.js");
|
|
7
|
+
const fakeSigner_js_1 = require("./fakeSigner.js");
|
|
8
|
+
const utils_js_1 = require("./utils.js");
|
|
9
|
+
class BaseSubmittableExtrinsic extends codecs_1.Extrinsic {
|
|
10
|
+
api;
|
|
11
|
+
constructor(api, call) {
|
|
12
|
+
super(api.registry, call);
|
|
13
|
+
this.api = api;
|
|
14
|
+
}
|
|
15
|
+
async paymentInfo(account, options) {
|
|
16
|
+
await this.sign(account, { ...options, signer: fakeSigner_js_1.fakeSigner });
|
|
17
|
+
const txU8a = this.toU8a();
|
|
18
|
+
const api = this.api;
|
|
19
|
+
return api.call.transactionPaymentApi.queryInfo(txU8a, txU8a.length);
|
|
20
|
+
}
|
|
21
|
+
async sign(fromAccount, options) {
|
|
22
|
+
const address = (0, utils_js_1.isKeyringPair)(fromAccount) ? fromAccount.address : fromAccount.toString();
|
|
23
|
+
const extra = new index_js_1.ExtraSignedExtension(this.api, {
|
|
24
|
+
signerAddress: address,
|
|
25
|
+
payloadOptions: options,
|
|
26
|
+
});
|
|
27
|
+
await extra.init();
|
|
28
|
+
const { signer } = options || {};
|
|
29
|
+
let signature;
|
|
30
|
+
if ((0, utils_js_1.isKeyringPair)(fromAccount)) {
|
|
31
|
+
signature = (0, utils_1.u8aToHex)((0, utils_js_1.signRaw)(fromAccount, extra.toRawPayload(this.callHex).data));
|
|
32
|
+
}
|
|
33
|
+
else if (signer?.signPayload) {
|
|
34
|
+
const result = await signer.signPayload(extra.toPayload(this.callHex));
|
|
35
|
+
signature = result.signature;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw new Error('Signer not found. Cannot sign the extrinsic!');
|
|
39
|
+
}
|
|
40
|
+
const { signatureTypeId } = this.registry.metadata.extrinsic;
|
|
41
|
+
const $Signature = this.registry.findCodec(signatureTypeId);
|
|
42
|
+
this.attachSignature({
|
|
43
|
+
address: address,
|
|
44
|
+
signature: $Signature.tryDecode(signature),
|
|
45
|
+
extra: extra.data,
|
|
46
|
+
});
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
async signAndSend(fromAccount, partialOptions, maybeCallback) {
|
|
50
|
+
const [options, callback] = this.#normalizeOptions(partialOptions, maybeCallback);
|
|
51
|
+
await this.sign(fromAccount, options);
|
|
52
|
+
return this.send(callback);
|
|
53
|
+
}
|
|
54
|
+
#normalizeOptions(partialOptions, callback) {
|
|
55
|
+
if ((0, utils_1.isFunction)(partialOptions)) {
|
|
56
|
+
return [{}, partialOptions];
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return [Object.assign({}, partialOptions), callback];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
send(callback) {
|
|
63
|
+
throw new Error('Unimplemented!');
|
|
64
|
+
}
|
|
65
|
+
async getSystemEventsAt(hash) {
|
|
66
|
+
const atApi = (await this.api.at(hash));
|
|
67
|
+
return await atApi.query.system.events();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.BaseSubmittableExtrinsic = BaseSubmittableExtrinsic;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SubmittableExtrinsic = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
5
|
+
const BaseSubmittableExtrinsic_js_1 = require("./BaseSubmittableExtrinsic.js");
|
|
6
|
+
const SubmittableResult_js_1 = require("./SubmittableResult.js");
|
|
7
|
+
/**
|
|
8
|
+
* @name SubmittableExtrinsic
|
|
9
|
+
* @description A wrapper around an Extrinsic that exposes methods to sign, send, and other utility around Extrinsic.
|
|
10
|
+
*/
|
|
11
|
+
class SubmittableExtrinsic extends BaseSubmittableExtrinsic_js_1.BaseSubmittableExtrinsic {
|
|
12
|
+
async dryRun(account, optionsOrHash) {
|
|
13
|
+
const dryRunFn = this.api.rpc.system_dryRun;
|
|
14
|
+
if ((0, utils_1.isHex)(optionsOrHash)) {
|
|
15
|
+
return dryRunFn(this.toHex(), optionsOrHash);
|
|
16
|
+
}
|
|
17
|
+
await this.sign(account, optionsOrHash);
|
|
18
|
+
return dryRunFn(this.toHex());
|
|
19
|
+
}
|
|
20
|
+
async send(callback) {
|
|
21
|
+
const isSubscription = !!callback;
|
|
22
|
+
const txHex = this.toHex();
|
|
23
|
+
const txHash = this.hash;
|
|
24
|
+
if (isSubscription) {
|
|
25
|
+
return this.api.rpc.author_submitAndWatchExtrinsic(txHex, async (status) => {
|
|
26
|
+
if (status.tag === 'InBlock' || status.tag === 'Finalized') {
|
|
27
|
+
const blockHash = status.value;
|
|
28
|
+
const [signedBlock, blockEvents] = await Promise.all([
|
|
29
|
+
this.api.rpc.chain_getBlock(blockHash),
|
|
30
|
+
this.getSystemEventsAt(blockHash),
|
|
31
|
+
]);
|
|
32
|
+
const txIndex = signedBlock.block.extrinsics.indexOf(txHex);
|
|
33
|
+
(0, utils_1.assert)(txIndex >= 0, 'Extrinsic not found!');
|
|
34
|
+
const events = blockEvents.filter(({ phase }) => phase.tag === 'ApplyExtrinsic' && phase.value === txIndex);
|
|
35
|
+
return callback(new SubmittableResult_js_1.SubmittableResult({ status, txHash, events, txIndex }));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return callback(new SubmittableResult_js_1.SubmittableResult({ status, txHash }));
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return this.api.rpc.author_submitExtrinsic(txHex);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.SubmittableExtrinsic = SubmittableExtrinsic;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SubmittableExtrinsicV2 = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
5
|
+
const BaseSubmittableExtrinsic_js_1 = require("./BaseSubmittableExtrinsic.js");
|
|
6
|
+
const SubmittableResult_js_1 = require("./SubmittableResult.js");
|
|
7
|
+
const errors_js_1 = require("./errors.js");
|
|
8
|
+
/**
|
|
9
|
+
* @name SubmittableExtrinsicV2
|
|
10
|
+
* @description Submittable extrinsic based on JSON-RPC v2
|
|
11
|
+
*/
|
|
12
|
+
class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic_js_1.BaseSubmittableExtrinsic {
|
|
13
|
+
api;
|
|
14
|
+
constructor(api, call) {
|
|
15
|
+
super(api, call);
|
|
16
|
+
this.api = api;
|
|
17
|
+
}
|
|
18
|
+
async #send(callback) {
|
|
19
|
+
const api = this.api;
|
|
20
|
+
const txHex = this.toHex();
|
|
21
|
+
const txHash = this.hash;
|
|
22
|
+
// validate the transaction
|
|
23
|
+
// https://github.com/paritytech/json-rpc-interface-spec/issues/55#issuecomment-1609011150
|
|
24
|
+
const finalizedHash = await this.api.chainHead.finalizedHash();
|
|
25
|
+
const validateTx = async (hash) => {
|
|
26
|
+
const apiAt = await api.at(hash);
|
|
27
|
+
return apiAt.call.taggedTransactionQueue.validateTransaction('External', txHex, hash);
|
|
28
|
+
};
|
|
29
|
+
const validation = await validateTx(finalizedHash);
|
|
30
|
+
if (validation.isOk) {
|
|
31
|
+
callback(new SubmittableResult_js_1.SubmittableResult({ status: { tag: 'Validated' }, txHash }));
|
|
32
|
+
}
|
|
33
|
+
else if (validation.isErr) {
|
|
34
|
+
throw new errors_js_1.InvalidTxError(`Invalid Tx: ${validation.err.tag} - ${validation.err.value.tag}`, validation);
|
|
35
|
+
}
|
|
36
|
+
const checkTxIsOnChain = async (blockHash) => {
|
|
37
|
+
if (blockHash === finalizedHash)
|
|
38
|
+
return;
|
|
39
|
+
const txs = await api.chainHead.body(blockHash);
|
|
40
|
+
const txIndex = txs.indexOf(txHex);
|
|
41
|
+
if (txIndex < 0) {
|
|
42
|
+
return checkTxIsOnChain(api.chainHead.findBlock(blockHash).parent);
|
|
43
|
+
}
|
|
44
|
+
const events = await this.getSystemEventsAt(blockHash);
|
|
45
|
+
const txEvents = events.filter(({ phase }) => phase.tag == 'ApplyExtrinsic' && phase.value === txIndex);
|
|
46
|
+
return {
|
|
47
|
+
blockHash,
|
|
48
|
+
index: txIndex,
|
|
49
|
+
events: txEvents,
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
let txFound;
|
|
53
|
+
let isSearching = false;
|
|
54
|
+
let searchQueue = new utils_1.AsyncQueue();
|
|
55
|
+
// TODO 1. move the searching logic into a different utility
|
|
56
|
+
// 2. properly cancel the work by actually cancel the on-going operations
|
|
57
|
+
const cancelPendingSearch = () => {
|
|
58
|
+
searchQueue.clear();
|
|
59
|
+
};
|
|
60
|
+
const cancelBodySearch = () => {
|
|
61
|
+
searchQueue.cancel();
|
|
62
|
+
};
|
|
63
|
+
const startSearching = (block) => {
|
|
64
|
+
return searchQueue.enqueue(async () => {
|
|
65
|
+
const found = await checkTxIsOnChain(block.hash);
|
|
66
|
+
if (found) {
|
|
67
|
+
cancelPendingSearch();
|
|
68
|
+
}
|
|
69
|
+
return found;
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const checkBestBlockIncluded = async (block, bestChainChanged) => {
|
|
73
|
+
if (bestChainChanged) {
|
|
74
|
+
if (isSearching) {
|
|
75
|
+
// if the best chain is changing, we cancel the current search
|
|
76
|
+
// and start searching on the current best chain
|
|
77
|
+
cancelBodySearch();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
if (txFound)
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
isSearching = true;
|
|
86
|
+
const inBlock = await startSearching(block);
|
|
87
|
+
if (!inBlock) {
|
|
88
|
+
if (txFound && bestChainChanged) {
|
|
89
|
+
txFound = undefined;
|
|
90
|
+
callback(new SubmittableResult_js_1.SubmittableResult({
|
|
91
|
+
status: { tag: 'NoLongerInBestChain' },
|
|
92
|
+
txHash,
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (txFound && bestChainChanged) {
|
|
98
|
+
if (txFound.blockHash === inBlock.blockHash)
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
txFound = inBlock;
|
|
102
|
+
const { index: txIndex, events, blockHash } = inBlock;
|
|
103
|
+
callback(new SubmittableResult_js_1.SubmittableResult({
|
|
104
|
+
status: { tag: 'BestChainBlockIncluded', value: { blockHash, txIndex } },
|
|
105
|
+
txHash,
|
|
106
|
+
events,
|
|
107
|
+
txIndex,
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// ignore this!
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
if (searchQueue.size === 0 && !searchQueue.isWorking) {
|
|
115
|
+
isSearching = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
let txUnsub;
|
|
120
|
+
// This whole thing is just to make sure
|
|
121
|
+
// that we're not calling stopBroadcastFn twice
|
|
122
|
+
let stopBroadcastFn;
|
|
123
|
+
let stopped = false;
|
|
124
|
+
const stopBroadcast = () => {
|
|
125
|
+
if (stopped)
|
|
126
|
+
return;
|
|
127
|
+
if (stopBroadcastFn) {
|
|
128
|
+
stopped = true;
|
|
129
|
+
stopBroadcastFn().catch(utils_1.noop);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const checkFinalizedBlockIncluded = async (block) => {
|
|
133
|
+
const inBlock = await checkTxIsOnChain(block.hash);
|
|
134
|
+
if (inBlock) {
|
|
135
|
+
const { index: txIndex, events, blockHash } = inBlock;
|
|
136
|
+
callback(new SubmittableResult_js_1.SubmittableResult({
|
|
137
|
+
status: { tag: 'Finalized', value: { blockHash, txIndex } },
|
|
138
|
+
txHash,
|
|
139
|
+
events,
|
|
140
|
+
txIndex,
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Revalidate the tx, just in-case it becomes invalid along the way
|
|
145
|
+
// Context: https://github.com/paritytech/json-rpc-interface-spec/pull/107#issuecomment-1906008814
|
|
146
|
+
const validation = await validateTx(block.hash);
|
|
147
|
+
if (validation.isOk)
|
|
148
|
+
return;
|
|
149
|
+
callback(new SubmittableResult_js_1.SubmittableResult({
|
|
150
|
+
status: {
|
|
151
|
+
tag: 'Invalid',
|
|
152
|
+
value: { error: `Invalid Tx: ${validation.err.tag} - ${validation.err.value.tag}` },
|
|
153
|
+
},
|
|
154
|
+
txHash,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
txUnsub().catch(utils_1.noop);
|
|
158
|
+
};
|
|
159
|
+
stopBroadcastFn = await api.txBroadcaster.broadcastTx(txHex);
|
|
160
|
+
callback(new SubmittableResult_js_1.SubmittableResult({
|
|
161
|
+
status: { tag: 'Broadcasting' },
|
|
162
|
+
txHash,
|
|
163
|
+
}));
|
|
164
|
+
const stopBestBlockTrackingFn = api.chainHead.on('bestBlock', checkBestBlockIncluded);
|
|
165
|
+
const stopFinalizedBlockTrackingFn = api.chainHead.on('finalizedBlock', checkFinalizedBlockIncluded);
|
|
166
|
+
const stopTracking = () => {
|
|
167
|
+
stopBestBlockTrackingFn();
|
|
168
|
+
stopFinalizedBlockTrackingFn();
|
|
169
|
+
cancelBodySearch();
|
|
170
|
+
};
|
|
171
|
+
txUnsub = async () => {
|
|
172
|
+
stopTracking();
|
|
173
|
+
stopBroadcast();
|
|
174
|
+
};
|
|
175
|
+
return txUnsub;
|
|
176
|
+
}
|
|
177
|
+
async send(callback) {
|
|
178
|
+
const isSubscription = !!callback;
|
|
179
|
+
if (isSubscription) {
|
|
180
|
+
return this.#send(callback);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
const defer = (0, utils_1.deferred)();
|
|
184
|
+
try {
|
|
185
|
+
// TODO handle timeout for this with the Drop status, just in-case we somehow can't find the tx in any block
|
|
186
|
+
const unsub = await this.#send(({ status, txHash }) => {
|
|
187
|
+
if (status.tag === 'BestChainBlockIncluded' || status.tag === 'Finalized') {
|
|
188
|
+
defer.resolve(txHash);
|
|
189
|
+
unsub().catch(utils_1.noop);
|
|
190
|
+
}
|
|
191
|
+
else if (status.tag === 'Invalid' || status.tag === 'Drop') {
|
|
192
|
+
defer.reject(new Error(status.value.error));
|
|
193
|
+
unsub().catch(utils_1.noop);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
catch (e) {
|
|
198
|
+
defer.reject(e);
|
|
199
|
+
}
|
|
200
|
+
return defer.promise;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.SubmittableExtrinsicV2 = SubmittableExtrinsicV2;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SubmittableResult = void 0;
|
|
4
|
+
class SubmittableResult {
|
|
5
|
+
status;
|
|
6
|
+
events;
|
|
7
|
+
dispatchInfo;
|
|
8
|
+
dispatchError;
|
|
9
|
+
txHash;
|
|
10
|
+
txIndex;
|
|
11
|
+
constructor({ events, status, txHash, txIndex }) {
|
|
12
|
+
this.events = events || [];
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.txHash = txHash;
|
|
15
|
+
this.txIndex = txIndex;
|
|
16
|
+
[this.dispatchInfo, this.dispatchError] = this._extractDispatchInfo();
|
|
17
|
+
}
|
|
18
|
+
_extractDispatchInfo() {
|
|
19
|
+
for (const { event } of this.events) {
|
|
20
|
+
const { pallet, palletEvent } = event;
|
|
21
|
+
if (pallet === 'System' && palletEvent.name === 'ExtrinsicFailed') {
|
|
22
|
+
const { dispatchInfo, dispatchError } = palletEvent.data;
|
|
23
|
+
return [dispatchInfo, dispatchError];
|
|
24
|
+
}
|
|
25
|
+
else if (pallet === 'System' && palletEvent.name === 'ExtrinsicSuccess') {
|
|
26
|
+
const { dispatchInfo } = palletEvent.data;
|
|
27
|
+
return [dispatchInfo, undefined];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return [undefined, undefined];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.SubmittableResult = SubmittableResult;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvalidTxError = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
5
|
+
/**
|
|
6
|
+
* This throws out if the extrinsic is invalid
|
|
7
|
+
* after verifying via `call.taggedTransactionQueue.validateTransaction`
|
|
8
|
+
*/
|
|
9
|
+
class InvalidTxError extends utils_1.DedotError {
|
|
10
|
+
data;
|
|
11
|
+
constructor(message, data) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.data = data;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.InvalidTxError = InvalidTxError;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fakeSigner = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
5
|
+
const FAKE_SIGNATURE = new Uint8Array(64 * 8).fill(0);
|
|
6
|
+
exports.fakeSigner = {
|
|
7
|
+
signPayload: async () => {
|
|
8
|
+
return {
|
|
9
|
+
id: Date.now(),
|
|
10
|
+
signature: (0, utils_1.u8aToHex)(FAKE_SIGNATURE),
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./errors.js"), exports);
|
|
18
|
+
__exportStar(require("./SubmittableResult.js"), exports);
|
|
19
|
+
__exportStar(require("./SubmittableExtrinsic.js"), exports);
|
|
20
|
+
__exportStar(require("./SubmittableExtrinsicV2.js"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.signRaw = exports.isKeyringPair = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
5
|
+
function isKeyringPair(account) {
|
|
6
|
+
return (0, utils_1.isFunction)(account.sign);
|
|
7
|
+
}
|
|
8
|
+
exports.isKeyringPair = isKeyringPair;
|
|
9
|
+
/**
|
|
10
|
+
* Sign a raw message
|
|
11
|
+
* @param signerPair
|
|
12
|
+
* @param raw
|
|
13
|
+
*/
|
|
14
|
+
function signRaw(signerPair, raw) {
|
|
15
|
+
const u8a = (0, utils_1.hexToU8a)(raw);
|
|
16
|
+
// Ref: https://github.com/paritytech/polkadot-sdk/blob/943697fa693a4da6ef481ef93df522accb7d0583/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs#L234-L238
|
|
17
|
+
const toSignRaw = u8a.length > 256 ? (0, utils_1.blake2AsU8a)(u8a, 256) : u8a;
|
|
18
|
+
return signerPair.sign(toSignRaw, { withType: true });
|
|
19
|
+
}
|
|
20
|
+
exports.signRaw = signRaw;
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./storage/index.js"), exports);
|
|
18
|
+
__exportStar(require("./extrinsic/index.js"), exports);
|
|
19
|
+
__exportStar(require("./executor/index.js"), exports);
|
|
20
|
+
__exportStar(require("./json-rpc/index.js"), exports);
|
|
21
|
+
__exportStar(require("./client/index.js"), exports);
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JsonRpcClient = exports.isJsonRpcProvider = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
5
|
+
const scaledResponses_js_1 = require("./scaledResponses.js");
|
|
6
|
+
const subscriptionsInfo_js_1 = require("./subscriptionsInfo.js");
|
|
7
|
+
const isJsonRpcProvider = (provider) => {
|
|
8
|
+
return (provider &&
|
|
9
|
+
(0, utils_1.isString)(provider.status) &&
|
|
10
|
+
(0, utils_1.isFunction)(provider.send) &&
|
|
11
|
+
(0, utils_1.isFunction)(provider.subscribe) &&
|
|
12
|
+
(0, utils_1.isFunction)(provider.connect) &&
|
|
13
|
+
(0, utils_1.isFunction)(provider.disconnect));
|
|
14
|
+
};
|
|
15
|
+
exports.isJsonRpcProvider = isJsonRpcProvider;
|
|
16
|
+
class JsonRpcClient extends utils_1.EventEmitter {
|
|
17
|
+
#options;
|
|
18
|
+
#provider;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super();
|
|
21
|
+
if ((0, exports.isJsonRpcProvider)(options)) {
|
|
22
|
+
this.#options = { provider: options };
|
|
23
|
+
this.#provider = options;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.#options = options;
|
|
27
|
+
this.#provider = options.provider;
|
|
28
|
+
}
|
|
29
|
+
(0, utils_1.assert)(this.#provider, 'A JsonRpcProvider is required');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Factory method to create a new JsonRpcClient instance
|
|
33
|
+
*
|
|
34
|
+
* @param options
|
|
35
|
+
*/
|
|
36
|
+
static async create(options) {
|
|
37
|
+
return new JsonRpcClient(options).connect();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Alias for __JsonRpcClient.create__
|
|
41
|
+
*
|
|
42
|
+
* @param options
|
|
43
|
+
*/
|
|
44
|
+
static async new(options) {
|
|
45
|
+
return JsonRpcClient.create(options);
|
|
46
|
+
}
|
|
47
|
+
get options() {
|
|
48
|
+
return this.#options;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @description Check connection status of the api instance
|
|
52
|
+
*/
|
|
53
|
+
get status() {
|
|
54
|
+
return this.provider.status;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* @description Get the JSON-RPC provider instance
|
|
58
|
+
*/
|
|
59
|
+
get provider() {
|
|
60
|
+
return this.#provider;
|
|
61
|
+
}
|
|
62
|
+
connect() {
|
|
63
|
+
return this.#doConnect();
|
|
64
|
+
}
|
|
65
|
+
async #doConnect() {
|
|
66
|
+
this.provider.on('connected', this.#onConnected);
|
|
67
|
+
this.provider.on('disconnected', this.#onDisconnected);
|
|
68
|
+
this.provider.on('reconnecting', this.#onReconnecting);
|
|
69
|
+
this.provider.on('error', this.#onError);
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
this.once('connected', () => {
|
|
73
|
+
resolve(this);
|
|
74
|
+
});
|
|
75
|
+
if (this.status === 'connected') {
|
|
76
|
+
this.#onConnected().catch(reject);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.provider.connect().catch(reject);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
#onConnected = async () => {
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
this.emit('connected');
|
|
86
|
+
};
|
|
87
|
+
#onDisconnected = async () => {
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
this.emit('disconnected');
|
|
90
|
+
};
|
|
91
|
+
#onReconnecting = async () => {
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
this.emit('reconnecting');
|
|
94
|
+
};
|
|
95
|
+
#onError = async (e) => {
|
|
96
|
+
// @ts-ignore
|
|
97
|
+
this.emit('error', e);
|
|
98
|
+
};
|
|
99
|
+
async disconnect() {
|
|
100
|
+
await this.#provider.disconnect();
|
|
101
|
+
this.clearEvents();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* @description Entry-point for executing JSON-RPCs to blockchain node.
|
|
105
|
+
*
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const client = new JsonRpcClient('wss://rpc.polkadot.io');
|
|
108
|
+
* await client.connect();
|
|
109
|
+
*
|
|
110
|
+
* // Subscribe to new heads
|
|
111
|
+
* client.rpc.chain_subscribeNewHeads((header) => {
|
|
112
|
+
* console.log(header);
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* // Execute arbitrary rpc method: `module_rpc_name`
|
|
116
|
+
* const result = await client.rpc.module_rpc_name();
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
get rpc() {
|
|
120
|
+
return new Proxy(this, {
|
|
121
|
+
get(target, property, receiver) {
|
|
122
|
+
const rpcMethod = property.toString();
|
|
123
|
+
return target.#doExecute(rpcMethod);
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
#doExecute(rpcName) {
|
|
128
|
+
const subscriptionInfo = this.options.subscriptions?.[rpcName] || subscriptionsInfo_js_1.subscriptionsInfo[rpcName];
|
|
129
|
+
const isSubscription = !!subscriptionInfo;
|
|
130
|
+
const fnRpc = async (...args) => {
|
|
131
|
+
const result = await this.provider.send(rpcName, args);
|
|
132
|
+
return this.#tryDecode(rpcName, result);
|
|
133
|
+
};
|
|
134
|
+
const fnSubRpc = async (...args) => {
|
|
135
|
+
const inArgs = args.slice();
|
|
136
|
+
const callback = inArgs.pop();
|
|
137
|
+
(0, utils_1.assert)((0, utils_1.isFunction)(callback), 'A callback is required for subscription');
|
|
138
|
+
const onNewMessage = (error, result, subscription) => {
|
|
139
|
+
if (error) {
|
|
140
|
+
console.error(error);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
callback(this.#tryDecode(rpcName, result), subscription);
|
|
144
|
+
};
|
|
145
|
+
const [subname, unsubscribe] = subscriptionInfo;
|
|
146
|
+
const subscription = await this.provider.subscribe({ subname, subscribe: rpcName, params: inArgs, unsubscribe }, onNewMessage);
|
|
147
|
+
return async () => {
|
|
148
|
+
await subscription.unsubscribe();
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
return isSubscription ? fnSubRpc : fnRpc;
|
|
152
|
+
}
|
|
153
|
+
#tryDecode(rpcName, raw) {
|
|
154
|
+
if (raw === null) {
|
|
155
|
+
// We use `undefined` to represent Option::None in the client
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
const $maybeCodec = this.options.scaledResponses?.[rpcName] || scaledResponses_js_1.scaledResponses[rpcName];
|
|
159
|
+
if ($maybeCodec) {
|
|
160
|
+
return $maybeCodec.tryDecode(raw);
|
|
161
|
+
}
|
|
162
|
+
return raw;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.JsonRpcClient = JsonRpcClient;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BlockUsage = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* A helper to track block hash usage
|
|
6
|
+
*/
|
|
7
|
+
class BlockUsage {
|
|
8
|
+
#usages = {};
|
|
9
|
+
use(blockHash) {
|
|
10
|
+
this.#usages[blockHash] = (this.#usages[blockHash] || 0) + 1;
|
|
11
|
+
}
|
|
12
|
+
release(blockHash) {
|
|
13
|
+
if (!this.#usages[blockHash])
|
|
14
|
+
return;
|
|
15
|
+
this.#usages[blockHash] -= 1;
|
|
16
|
+
}
|
|
17
|
+
usage(blockHash) {
|
|
18
|
+
return this.#usages[blockHash] || 0;
|
|
19
|
+
}
|
|
20
|
+
clear() {
|
|
21
|
+
this.#usages = {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.BlockUsage = BlockUsage;
|