@dedot/api 0.15.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/chaintypes/substrate/index.d.ts +21 -1
- package/cjs/client/BaseSubstrateClient.js +12 -3
- package/cjs/client/DedotClient.js +51 -11
- package/cjs/client/LegacyClient.js +4 -5
- package/cjs/executor/Executor.js +1 -0
- package/cjs/executor/v2/StorageQueryExecutorV2.js +1 -3
- package/cjs/executor/v2/TxExecutorV2.js +5 -3
- package/cjs/json-rpc/group/Archive.js +232 -0
- package/cjs/json-rpc/group/ChainHead/ChainHead.js +149 -52
- package/cjs/json-rpc/group/ChainHead/error.js +5 -0
- package/cjs/json-rpc/group/index.js +1 -0
- package/cjs/json-rpc/subscriptionsInfo.js +4 -0
- package/cjs/storage/LegacyStorageQuery.js +5 -0
- package/cjs/storage/NewStorageQuery.js +5 -0
- package/client/BaseSubstrateClient.d.ts +8 -6
- package/client/BaseSubstrateClient.js +13 -4
- package/client/DedotClient.d.ts +11 -4
- package/client/DedotClient.js +54 -14
- package/client/LegacyClient.d.ts +2 -2
- package/client/LegacyClient.js +4 -5
- package/executor/Executor.d.ts +5 -5
- package/executor/Executor.js +1 -0
- package/executor/StorageQueryExecutor.d.ts +2 -2
- package/executor/v2/RuntimeApiExecutorV2.d.ts +2 -2
- package/executor/v2/StorageQueryExecutorV2.d.ts +4 -4
- package/executor/v2/StorageQueryExecutorV2.js +1 -3
- package/executor/v2/TxExecutorV2.d.ts +2 -1
- package/executor/v2/TxExecutorV2.js +5 -3
- package/executor/v2/ViewFunctionExecutorV2.d.ts +2 -2
- package/extrinsic/extensions/SignedExtension.d.ts +3 -3
- package/extrinsic/submittable/BaseSubmittableExtrinsic.d.ts +2 -2
- package/extrinsic/submittable/SubmittableExtrinsicV2.d.ts +2 -2
- package/json-rpc/group/Archive.d.ts +134 -0
- package/json-rpc/group/Archive.js +228 -0
- package/json-rpc/group/ChainHead/ChainHead.d.ts +21 -0
- package/json-rpc/group/ChainHead/ChainHead.js +150 -53
- package/json-rpc/group/ChainHead/error.d.ts +3 -0
- package/json-rpc/group/ChainHead/error.js +5 -0
- package/json-rpc/group/index.d.ts +1 -0
- package/json-rpc/group/index.js +1 -0
- package/json-rpc/subscriptionsInfo.js +4 -0
- package/package.json +9 -9
- package/storage/BaseStorageQuery.d.ts +5 -6
- package/storage/LegacyStorageQuery.d.ts +4 -3
- package/storage/LegacyStorageQuery.js +5 -0
- package/storage/NewStorageQuery.d.ts +4 -3
- package/storage/NewStorageQuery.js +5 -0
- package/storage/QueryableStorage.d.ts +2 -2
- package/types.d.ts +11 -6
package/client/LegacyClient.js
CHANGED
|
@@ -46,7 +46,6 @@ export class LegacyClient// prettier-end-here
|
|
|
46
46
|
extends BaseSubstrateClient {
|
|
47
47
|
#runtimeSubscriptionUnsub;
|
|
48
48
|
#healthTimer;
|
|
49
|
-
#apiAtCache = {};
|
|
50
49
|
/**
|
|
51
50
|
* Use factory methods (`create`, `new`) to create `Dedot` instances.
|
|
52
51
|
*
|
|
@@ -93,7 +92,6 @@ export class LegacyClient// prettier-end-here
|
|
|
93
92
|
}
|
|
94
93
|
cleanUp() {
|
|
95
94
|
super.cleanUp();
|
|
96
|
-
this.#apiAtCache = {};
|
|
97
95
|
this.#healthTimer = undefined;
|
|
98
96
|
this.#runtimeSubscriptionUnsub = undefined;
|
|
99
97
|
}
|
|
@@ -229,8 +227,9 @@ export class LegacyClient// prettier-end-here
|
|
|
229
227
|
* @param hash
|
|
230
228
|
*/
|
|
231
229
|
async at(hash) {
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
const cached = this._apiAtCache.get(hash);
|
|
231
|
+
if (cached)
|
|
232
|
+
return cached;
|
|
234
233
|
const targetVersion = await this.#getRuntimeVersion(hash);
|
|
235
234
|
let metadata = this.metadata;
|
|
236
235
|
let registry = this.registry;
|
|
@@ -253,7 +252,7 @@ export class LegacyClient// prettier-end-here
|
|
|
253
252
|
api.call = newProxyChain({ executor: new RuntimeApiExecutor(api) });
|
|
254
253
|
api.events = newProxyChain({ executor: new EventExecutor(api) });
|
|
255
254
|
api.errors = newProxyChain({ executor: new ErrorExecutor(api) });
|
|
256
|
-
this
|
|
255
|
+
this._apiAtCache.set(hash, api);
|
|
257
256
|
return api;
|
|
258
257
|
}
|
|
259
258
|
getStorageQuery() {
|
package/executor/Executor.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BlockHash, PalletDefLatest } from '@dedot/codecs';
|
|
2
2
|
import type { GenericSubstrateApi } from '@dedot/types';
|
|
3
3
|
import { HexString } from '@dedot/utils';
|
|
4
|
-
import { ISubstrateClientAt } from '../types.js';
|
|
4
|
+
import { ISubstrateClient, ISubstrateClientAt } from '../types.js';
|
|
5
5
|
export interface StateCallParams {
|
|
6
6
|
func: string;
|
|
7
7
|
params: HexString;
|
|
@@ -13,10 +13,10 @@ export interface StateCallParams {
|
|
|
13
13
|
*/
|
|
14
14
|
export declare abstract class Executor<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> {
|
|
15
15
|
#private;
|
|
16
|
-
readonly client: ISubstrateClientAt<ChainApi>;
|
|
17
|
-
constructor(client: ISubstrateClientAt<ChainApi>, atBlockHash?: BlockHash);
|
|
18
|
-
get atBlockHash():
|
|
19
|
-
get registry(): import("@dedot/codecs").PortableRegistry
|
|
16
|
+
readonly client: ISubstrateClientAt<ChainApi> | ISubstrateClient<ChainApi, any>;
|
|
17
|
+
constructor(client: ISubstrateClientAt<ChainApi> | ISubstrateClient<ChainApi, any>, atBlockHash?: BlockHash);
|
|
18
|
+
get atBlockHash(): any;
|
|
19
|
+
get registry(): import("@dedot/codecs").PortableRegistry<ChainApi>;
|
|
20
20
|
get metadata(): {
|
|
21
21
|
types: {
|
|
22
22
|
id: number;
|
package/executor/Executor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BlockHash, Option, StorageData, StorageKey } from '@dedot/codecs';
|
|
2
|
-
import type { AsyncMethod, Callback, GenericStorageQuery, GenericSubstrateApi,
|
|
2
|
+
import type { AsyncMethod, Callback, GenericStorageQuery, GenericSubstrateApi, Unsub } from '@dedot/types';
|
|
3
3
|
import { type BaseStorageQuery, QueryableStorage } from '../storage/index.js';
|
|
4
4
|
import { Executor } from './Executor.js';
|
|
5
5
|
/**
|
|
@@ -9,7 +9,7 @@ import { Executor } from './Executor.js';
|
|
|
9
9
|
export declare class StorageQueryExecutor<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends Executor<ChainApi> {
|
|
10
10
|
doExecute(pallet: string, storage: string): GenericStorageQuery;
|
|
11
11
|
protected exposeStorageMapMethods(entry: QueryableStorage): Record<string, AsyncMethod>;
|
|
12
|
-
protected getStorageQuery(): BaseStorageQuery
|
|
12
|
+
protected getStorageQuery(): BaseStorageQuery;
|
|
13
13
|
protected queryStorage(keys: StorageKey[], hash?: BlockHash): Promise<Record<StorageKey, Option<StorageData>>>;
|
|
14
14
|
protected subscribeStorage(keys: StorageKey[], callback: Callback<Array<StorageData | undefined>>): Promise<Unsub>;
|
|
15
15
|
}
|
|
@@ -2,7 +2,7 @@ import type { BlockHash } from '@dedot/codecs';
|
|
|
2
2
|
import type { GenericSubstrateApi } from '@dedot/types';
|
|
3
3
|
import { HexString } from '@dedot/utils';
|
|
4
4
|
import { ChainHead } from '../../json-rpc/index.js';
|
|
5
|
-
import { ISubstrateClientAt } from '../../types.js';
|
|
5
|
+
import { ISubstrateClient, ISubstrateClientAt } from '../../types.js';
|
|
6
6
|
import { StateCallParams } from '../Executor.js';
|
|
7
7
|
import { RuntimeApiExecutor } from '../RuntimeApiExecutor.js';
|
|
8
8
|
/**
|
|
@@ -10,6 +10,6 @@ import { RuntimeApiExecutor } from '../RuntimeApiExecutor.js';
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class RuntimeApiExecutorV2<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends RuntimeApiExecutor<ChainApi> {
|
|
12
12
|
chainHead: ChainHead;
|
|
13
|
-
constructor(client: ISubstrateClientAt<ChainApi>, chainHead: ChainHead, atBlockHash?: BlockHash);
|
|
13
|
+
constructor(client: ISubstrateClientAt<ChainApi> | ISubstrateClient<ChainApi, any>, chainHead: ChainHead, atBlockHash?: BlockHash);
|
|
14
14
|
protected stateCall(callParams: StateCallParams): Promise<HexString>;
|
|
15
15
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { BlockHash } from '@dedot/codecs';
|
|
2
|
-
import type { AsyncMethod, GenericSubstrateApi
|
|
2
|
+
import type { AsyncMethod, GenericSubstrateApi } from '@dedot/types';
|
|
3
3
|
import { ChainHead } from '../../json-rpc/index.js';
|
|
4
4
|
import { type BaseStorageQuery, QueryableStorage } from '../../storage/index.js';
|
|
5
|
-
import { ISubstrateClientAt } from '../../types.js';
|
|
5
|
+
import { ISubstrateClient, ISubstrateClientAt } from '../../types.js';
|
|
6
6
|
import { StorageQueryExecutor } from '../StorageQueryExecutor.js';
|
|
7
7
|
/**
|
|
8
8
|
* @name StorageQueryExecutorV2
|
|
9
9
|
*/
|
|
10
10
|
export declare class StorageQueryExecutorV2<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends StorageQueryExecutor<ChainApi> {
|
|
11
11
|
chainHead: ChainHead;
|
|
12
|
-
constructor(client: ISubstrateClientAt<ChainApi>, chainHead: ChainHead, atBlockHash?: BlockHash);
|
|
12
|
+
constructor(client: ISubstrateClientAt<ChainApi> | ISubstrateClient<ChainApi, any>, chainHead: ChainHead, atBlockHash?: BlockHash);
|
|
13
13
|
protected exposeStorageMapMethods(entry: QueryableStorage): Record<string, AsyncMethod>;
|
|
14
|
-
protected getStorageQuery(): BaseStorageQuery
|
|
14
|
+
protected getStorageQuery(): BaseStorageQuery;
|
|
15
15
|
}
|
|
@@ -19,9 +19,7 @@ export class StorageQueryExecutorV2 extends StorageQueryExecutor {
|
|
|
19
19
|
const entries = async (...args) => {
|
|
20
20
|
const withArgs = !!args && args.length > 0;
|
|
21
21
|
const key = withArgs ? entry.encodeKey(args, true) : entry.prefixKey;
|
|
22
|
-
const results = await this.chainHead.storage([
|
|
23
|
-
{ type: 'descendantsValues', key },
|
|
24
|
-
]);
|
|
22
|
+
const results = await this.chainHead.storage([{ type: 'descendantsValues', key }]);
|
|
25
23
|
return results.map(({ key, value }) => [
|
|
26
24
|
entry.decodeKey(key),
|
|
27
25
|
entry.decodeValue(value),
|
|
@@ -6,6 +6,7 @@ import { TxExecutor } from '../TxExecutor.js';
|
|
|
6
6
|
* @description Execute a transaction instruction, returns a submittable extrinsic
|
|
7
7
|
*/
|
|
8
8
|
export declare class TxExecutorV2<ChainApi extends VersionedGenericSubstrateApi = VersionedGenericSubstrateApi> extends TxExecutor<ChainApi[RpcVersion]> {
|
|
9
|
-
|
|
9
|
+
readonly client: DedotClient<ChainApi>;
|
|
10
|
+
constructor(client: DedotClient<ChainApi>);
|
|
10
11
|
protected createExtrinsic(call: IRuntimeTxCall): any;
|
|
11
12
|
}
|
|
@@ -6,9 +6,11 @@ import { TxExecutor } from '../TxExecutor.js';
|
|
|
6
6
|
* @description Execute a transaction instruction, returns a submittable extrinsic
|
|
7
7
|
*/
|
|
8
8
|
export class TxExecutorV2 extends TxExecutor {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
client;
|
|
10
|
+
constructor(client) {
|
|
11
|
+
assert(client.rpcVersion === 'v2', 'Only supports JSON-RPC v2');
|
|
12
|
+
super(client);
|
|
13
|
+
this.client = client;
|
|
12
14
|
}
|
|
13
15
|
createExtrinsic(call) {
|
|
14
16
|
return new SubmittableExtrinsicV2(this.client, call);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { GenericSubstrateApi } from '@dedot/types';
|
|
2
2
|
import { HexString } from '@dedot/utils';
|
|
3
3
|
import { ChainHead } from '../../json-rpc/index.js';
|
|
4
|
-
import { ISubstrateClientAt } from '../../types.js';
|
|
4
|
+
import { ISubstrateClient, ISubstrateClientAt } from '../../types.js';
|
|
5
5
|
import { StateCallParams } from '../Executor.js';
|
|
6
6
|
import { ViewFunctionExecutor } from '../ViewFunctionExecutor.js';
|
|
7
7
|
/**
|
|
@@ -9,6 +9,6 @@ import { ViewFunctionExecutor } from '../ViewFunctionExecutor.js';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class ViewFunctionExecutorV2<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends ViewFunctionExecutor<ChainApi> {
|
|
11
11
|
chainHead: ChainHead;
|
|
12
|
-
constructor(client: ISubstrateClientAt<ChainApi>, chainHead: ChainHead);
|
|
12
|
+
constructor(client: ISubstrateClientAt<ChainApi> | ISubstrateClient<ChainApi, any>, chainHead: ChainHead);
|
|
13
13
|
protected stateCall(callParams: StateCallParams): Promise<HexString>;
|
|
14
14
|
}
|
|
@@ -19,17 +19,17 @@ interface SignedExtensionOptions {
|
|
|
19
19
|
payloadOptions?: Partial<PayloadOptions>;
|
|
20
20
|
}
|
|
21
21
|
export declare abstract class SignedExtension<Data extends any = {}, AdditionalSigned extends any = []> implements ISignedExtension {
|
|
22
|
-
readonly client: ISubstrateClient
|
|
22
|
+
readonly client: ISubstrateClient<any, any>;
|
|
23
23
|
readonly options?: SignedExtensionOptions | undefined;
|
|
24
24
|
data: Data;
|
|
25
25
|
additionalSigned: AdditionalSigned;
|
|
26
|
-
constructor(client: ISubstrateClient, options?: SignedExtensionOptions | undefined);
|
|
26
|
+
constructor(client: ISubstrateClient<any, any>, options?: SignedExtensionOptions | undefined);
|
|
27
27
|
init(): Promise<void>;
|
|
28
28
|
fromPayload(payload: SignerPayloadJSON): Promise<void>;
|
|
29
29
|
get identifier(): string;
|
|
30
30
|
get $Data(): $.AnyShape;
|
|
31
31
|
get $AdditionalSigned(): $.AnyShape;
|
|
32
|
-
get registry(): PortableRegistry
|
|
32
|
+
get registry(): PortableRegistry<any>;
|
|
33
33
|
get signedExtensionDef(): {
|
|
34
34
|
ident: string;
|
|
35
35
|
typeId: number;
|
|
@@ -9,8 +9,8 @@ interface TxHooks {
|
|
|
9
9
|
}
|
|
10
10
|
export declare abstract class BaseSubmittableExtrinsic extends Extrinsic implements ISubmittableExtrinsic {
|
|
11
11
|
#private;
|
|
12
|
-
readonly client: ISubstrateClient
|
|
13
|
-
constructor(client: ISubstrateClient
|
|
12
|
+
readonly client: ISubstrateClient<any>;
|
|
13
|
+
constructor(client: ISubstrateClient<any>, call: IRuntimeTxCall);
|
|
14
14
|
withHooks(hooks: TxHooks): void;
|
|
15
15
|
protected transformTxResult<R extends ISubmittableResult = ISubmittableResult>(result: ISubmittableResult): R;
|
|
16
16
|
paymentInfo(account: AddressOrPair, options?: Partial<PayloadOptions>): Promise<TxPaymentInfo>;
|
|
@@ -7,8 +7,8 @@ import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
|
|
|
7
7
|
*/
|
|
8
8
|
export declare class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
|
|
9
9
|
#private;
|
|
10
|
-
client: DedotClient
|
|
11
|
-
constructor(client: DedotClient
|
|
10
|
+
client: DedotClient<any>;
|
|
11
|
+
constructor(client: DedotClient<any>, call: IRuntimeTxCall);
|
|
12
12
|
send(): TxHash;
|
|
13
13
|
send(callback: Callback): TxUnsub;
|
|
14
14
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { BlockHash, Option } from '@dedot/codecs';
|
|
2
|
+
import { ArchiveStorageResult, PaginatedStorageQuery } from '@dedot/types/json-rpc';
|
|
3
|
+
import { HexString } from '@dedot/utils';
|
|
4
|
+
import { IJsonRpcClient } from '../../types.js';
|
|
5
|
+
import { JsonRpcGroup, JsonRpcGroupOptions } from './JsonRpcGroup.js';
|
|
6
|
+
/**
|
|
7
|
+
* @name Archive
|
|
8
|
+
* Archive JSON-RPC methods for accessing historical blockchain data.
|
|
9
|
+
* Functions with the `archive` prefix allow obtaining the state of the chain
|
|
10
|
+
* at any point in the present or in the past.
|
|
11
|
+
*
|
|
12
|
+
* JSON-RPC V2: https://paritytech.github.io/json-rpc-interface-spec/api/archive.html
|
|
13
|
+
*/
|
|
14
|
+
export declare class Archive extends JsonRpcGroup {
|
|
15
|
+
#private;
|
|
16
|
+
constructor(client: IJsonRpcClient, options?: Partial<JsonRpcGroupOptions>);
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves the body (list of transactions) of a given block.
|
|
19
|
+
* Returns an array of strings containing the hexadecimal-encoded SCALE-codec-encoded
|
|
20
|
+
* transactions in that block. If no block with that hash is found, null.
|
|
21
|
+
*
|
|
22
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
23
|
+
* @returns Array of transaction hashes or null if block not found
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // Get transactions from current finalized block
|
|
28
|
+
* const transactions = await archive.body();
|
|
29
|
+
*
|
|
30
|
+
* // Get transactions from specific block
|
|
31
|
+
* const transactions = await archive.body('0x1234...');
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
body(hash?: BlockHash): Promise<Option<Array<HexString>>>;
|
|
35
|
+
/**
|
|
36
|
+
* Get the chain's genesis hash.
|
|
37
|
+
* Returns a string containing the hexadecimal-encoded hash of the genesis block of the chain.
|
|
38
|
+
* This value is cached after the first call.
|
|
39
|
+
*
|
|
40
|
+
* @returns The genesis block hash
|
|
41
|
+
*/
|
|
42
|
+
genesisHash(): Promise<HexString>;
|
|
43
|
+
/**
|
|
44
|
+
* Get the block's header.
|
|
45
|
+
* Returns a string containing the hexadecimal-encoded SCALE-codec encoding header of the block.
|
|
46
|
+
*
|
|
47
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
48
|
+
* @returns The encoded block header or null if block not found
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* // Get header of current finalized block
|
|
53
|
+
* const header = await archive.header();
|
|
54
|
+
*
|
|
55
|
+
* // Get header of specific block
|
|
56
|
+
* const header = await archive.header('0x1234...');
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
header(hash?: BlockHash): Promise<Option<HexString>>;
|
|
60
|
+
/**
|
|
61
|
+
* Get the height of the current finalized block.
|
|
62
|
+
* Returns an integer height of the current finalized block of the chain.
|
|
63
|
+
*
|
|
64
|
+
* @returns The height of the finalized block
|
|
65
|
+
*/
|
|
66
|
+
finalizedHeight(): Promise<number>;
|
|
67
|
+
/**
|
|
68
|
+
* Get the hash of the current finalized block.
|
|
69
|
+
* Returns a string containing the hexadecimal-encoded hash of the current finalized block.
|
|
70
|
+
* This is a convenience method that combines finalizedHeight() and hashByHeight().
|
|
71
|
+
*
|
|
72
|
+
* @returns The hash of the current finalized block
|
|
73
|
+
*/
|
|
74
|
+
finalizedHash(): Promise<HexString>;
|
|
75
|
+
/**
|
|
76
|
+
* Get the hashes of blocks from the given height.
|
|
77
|
+
* Returns an array (possibly empty) of strings containing hexadecimal-encoded hashes of block headers.
|
|
78
|
+
*
|
|
79
|
+
* Note: For heights <= finalized height, there is guaranteed to be one block.
|
|
80
|
+
* For heights > finalized height, there may be zero, one or multiple blocks depending on forks.
|
|
81
|
+
*
|
|
82
|
+
* @param height - The block height
|
|
83
|
+
* @returns Array of block hashes at the given height
|
|
84
|
+
*/
|
|
85
|
+
hashByHeight(height: number): Promise<Array<HexString>>;
|
|
86
|
+
/**
|
|
87
|
+
* Call into the Runtime API at a specified block's state.
|
|
88
|
+
*
|
|
89
|
+
* @param func - The runtime API function to call
|
|
90
|
+
* @param params - The parameters for the function call (SCALE-encoded)
|
|
91
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
92
|
+
* @returns The result of the runtime call
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // Call Core_version on current finalized block
|
|
97
|
+
* const version = await archive.call('Core_version', '0x');
|
|
98
|
+
*
|
|
99
|
+
* // Call Core_version on specific block
|
|
100
|
+
* const version = await archive.call('Core_version', '0x', '0x1234...');
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
call(func: string, params: HexString, hash?: BlockHash): Promise<HexString>;
|
|
104
|
+
/**
|
|
105
|
+
* Returns storage entries at a specific block's state.
|
|
106
|
+
* This method collects all storage events and returns them as a single result.
|
|
107
|
+
*
|
|
108
|
+
* @param items - Array of storage queries with optional pagination
|
|
109
|
+
* @param childTrie - Optional child trie key
|
|
110
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
111
|
+
* @returns Storage results array
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* // Query storage from current finalized block
|
|
116
|
+
* const results = await archive.storage([{ key: '0x1234', type: 'value' }]);
|
|
117
|
+
*
|
|
118
|
+
* // Query storage from specific block
|
|
119
|
+
* const results = await archive.storage([{ key: '0x1234', type: 'value' }], null, '0xabcd...');
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
storage(items: Array<PaginatedStorageQuery>, childTrie?: HexString | null, hash?: BlockHash): Promise<ArchiveStorageResult>;
|
|
123
|
+
/**
|
|
124
|
+
* Clears the internal cache used for storing archive query results.
|
|
125
|
+
* This can be useful for memory management or when you want to force fresh data retrieval.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* // Clear all cached results
|
|
130
|
+
* archive.clearCache();
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
clearCache(): void;
|
|
134
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { DedotError, LRUCache } from '@dedot/utils';
|
|
2
|
+
import { JsonRpcGroup } from './JsonRpcGroup.js';
|
|
3
|
+
const ARCHIVE_CACHE_CAPACITY = 256;
|
|
4
|
+
const ARCHIVE_CACHE_TTL = 60_000; // 1 minutes - archive data is immutable
|
|
5
|
+
/**
|
|
6
|
+
* @name Archive
|
|
7
|
+
* Archive JSON-RPC methods for accessing historical blockchain data.
|
|
8
|
+
* Functions with the `archive` prefix allow obtaining the state of the chain
|
|
9
|
+
* at any point in the present or in the past.
|
|
10
|
+
*
|
|
11
|
+
* JSON-RPC V2: https://paritytech.github.io/json-rpc-interface-spec/api/archive.html
|
|
12
|
+
*/
|
|
13
|
+
export class Archive extends JsonRpcGroup {
|
|
14
|
+
#genesisHash;
|
|
15
|
+
#cache;
|
|
16
|
+
constructor(client, options) {
|
|
17
|
+
super(client, { prefix: 'archive', supportedVersions: ['unstable', 'v1'], ...options });
|
|
18
|
+
this.#cache = new LRUCache(ARCHIVE_CACHE_CAPACITY, ARCHIVE_CACHE_TTL);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves the body (list of transactions) of a given block.
|
|
22
|
+
* Returns an array of strings containing the hexadecimal-encoded SCALE-codec-encoded
|
|
23
|
+
* transactions in that block. If no block with that hash is found, null.
|
|
24
|
+
*
|
|
25
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
26
|
+
* @returns Array of transaction hashes or null if block not found
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Get transactions from current finalized block
|
|
31
|
+
* const transactions = await archive.body();
|
|
32
|
+
*
|
|
33
|
+
* // Get transactions from specific block
|
|
34
|
+
* const transactions = await archive.body('0x1234...');
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
async body(hash) {
|
|
38
|
+
const blockHash = hash || (await this.finalizedHash());
|
|
39
|
+
const cacheKey = `${blockHash}::body`;
|
|
40
|
+
const cached = this.#cache.get(cacheKey);
|
|
41
|
+
if (cached !== null) {
|
|
42
|
+
return cached;
|
|
43
|
+
}
|
|
44
|
+
const result = await this.send('body', blockHash);
|
|
45
|
+
this.#cache.set(cacheKey, result);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the chain's genesis hash.
|
|
50
|
+
* Returns a string containing the hexadecimal-encoded hash of the genesis block of the chain.
|
|
51
|
+
* This value is cached after the first call.
|
|
52
|
+
*
|
|
53
|
+
* @returns The genesis block hash
|
|
54
|
+
*/
|
|
55
|
+
async genesisHash() {
|
|
56
|
+
if (!this.#genesisHash) {
|
|
57
|
+
this.#genesisHash = await this.send('genesisHash');
|
|
58
|
+
}
|
|
59
|
+
return this.#genesisHash;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get the block's header.
|
|
63
|
+
* Returns a string containing the hexadecimal-encoded SCALE-codec encoding header of the block.
|
|
64
|
+
*
|
|
65
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
66
|
+
* @returns The encoded block header or null if block not found
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // Get header of current finalized block
|
|
71
|
+
* const header = await archive.header();
|
|
72
|
+
*
|
|
73
|
+
* // Get header of specific block
|
|
74
|
+
* const header = await archive.header('0x1234...');
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
async header(hash) {
|
|
78
|
+
const blockHash = hash || (await this.finalizedHash());
|
|
79
|
+
const cacheKey = `${blockHash}::header`;
|
|
80
|
+
const cached = this.#cache.get(cacheKey);
|
|
81
|
+
if (cached !== null) {
|
|
82
|
+
return cached;
|
|
83
|
+
}
|
|
84
|
+
const result = await this.send('header', blockHash);
|
|
85
|
+
this.#cache.set(cacheKey, result);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the height of the current finalized block.
|
|
90
|
+
* Returns an integer height of the current finalized block of the chain.
|
|
91
|
+
*
|
|
92
|
+
* @returns The height of the finalized block
|
|
93
|
+
*/
|
|
94
|
+
async finalizedHeight() {
|
|
95
|
+
return this.send('finalizedHeight');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the hash of the current finalized block.
|
|
99
|
+
* Returns a string containing the hexadecimal-encoded hash of the current finalized block.
|
|
100
|
+
* This is a convenience method that combines finalizedHeight() and hashByHeight().
|
|
101
|
+
*
|
|
102
|
+
* @returns The hash of the current finalized block
|
|
103
|
+
*/
|
|
104
|
+
async finalizedHash() {
|
|
105
|
+
const height = await this.finalizedHeight();
|
|
106
|
+
const hashes = await this.hashByHeight(height);
|
|
107
|
+
if (hashes.length === 0) {
|
|
108
|
+
throw new Error(`No block found at finalized height ${height}`);
|
|
109
|
+
}
|
|
110
|
+
return hashes[0];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get the hashes of blocks from the given height.
|
|
114
|
+
* Returns an array (possibly empty) of strings containing hexadecimal-encoded hashes of block headers.
|
|
115
|
+
*
|
|
116
|
+
* Note: For heights <= finalized height, there is guaranteed to be one block.
|
|
117
|
+
* For heights > finalized height, there may be zero, one or multiple blocks depending on forks.
|
|
118
|
+
*
|
|
119
|
+
* @param height - The block height
|
|
120
|
+
* @returns Array of block hashes at the given height
|
|
121
|
+
*/
|
|
122
|
+
async hashByHeight(height) {
|
|
123
|
+
return this.send('hashByHeight', height);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Call into the Runtime API at a specified block's state.
|
|
127
|
+
*
|
|
128
|
+
* @param func - The runtime API function to call
|
|
129
|
+
* @param params - The parameters for the function call (SCALE-encoded)
|
|
130
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
131
|
+
* @returns The result of the runtime call
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* // Call Core_version on current finalized block
|
|
136
|
+
* const version = await archive.call('Core_version', '0x');
|
|
137
|
+
*
|
|
138
|
+
* // Call Core_version on specific block
|
|
139
|
+
* const version = await archive.call('Core_version', '0x', '0x1234...');
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
async call(func, params, hash) {
|
|
143
|
+
const blockHash = hash || (await this.finalizedHash());
|
|
144
|
+
const cacheKey = `${blockHash}::call::${func}::${params}`;
|
|
145
|
+
const cached = this.#cache.get(cacheKey);
|
|
146
|
+
if (cached !== null) {
|
|
147
|
+
return cached;
|
|
148
|
+
}
|
|
149
|
+
const result = await this.send('call', blockHash, func, params);
|
|
150
|
+
if (!result.success) {
|
|
151
|
+
throw new DedotError(result.error);
|
|
152
|
+
}
|
|
153
|
+
this.#cache.set(cacheKey, result.value);
|
|
154
|
+
return result.value;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Returns storage entries at a specific block's state via subscription.
|
|
158
|
+
*
|
|
159
|
+
* @param items - Array of storage queries with optional pagination
|
|
160
|
+
* @param childTrie - Optional child trie key
|
|
161
|
+
* @param callback - Callback to receive storage events
|
|
162
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
163
|
+
* @returns Unsubscribe function
|
|
164
|
+
*/
|
|
165
|
+
async #storageSubscription(items, childTrie, callback, hash) {
|
|
166
|
+
const blockHash = hash || (await this.finalizedHash());
|
|
167
|
+
return this.send('storage', blockHash, items, childTrie, callback);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns storage entries at a specific block's state.
|
|
171
|
+
* This method collects all storage events and returns them as a single result.
|
|
172
|
+
*
|
|
173
|
+
* @param items - Array of storage queries with optional pagination
|
|
174
|
+
* @param childTrie - Optional child trie key
|
|
175
|
+
* @param hash - The block hash (optional, defaults to current finalized block)
|
|
176
|
+
* @returns Storage results array
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* // Query storage from current finalized block
|
|
181
|
+
* const results = await archive.storage([{ key: '0x1234', type: 'value' }]);
|
|
182
|
+
*
|
|
183
|
+
* // Query storage from specific block
|
|
184
|
+
* const results = await archive.storage([{ key: '0x1234', type: 'value' }], null, '0xabcd...');
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
async storage(items, childTrie, hash) {
|
|
188
|
+
return new Promise(async (resolve, reject) => {
|
|
189
|
+
const results = [];
|
|
190
|
+
const blockHash = hash || (await this.finalizedHash());
|
|
191
|
+
// Generate cache key
|
|
192
|
+
const cacheKey = `${blockHash}::storage::${JSON.stringify(items)}::${childTrie ?? null}`;
|
|
193
|
+
// Check cache
|
|
194
|
+
const cached = this.#cache.get(cacheKey);
|
|
195
|
+
if (cached !== null) {
|
|
196
|
+
return resolve(cached);
|
|
197
|
+
}
|
|
198
|
+
this.#storageSubscription(items, childTrie || null, (event) => {
|
|
199
|
+
switch (event.event) {
|
|
200
|
+
case 'storage':
|
|
201
|
+
results.push(event);
|
|
202
|
+
break;
|
|
203
|
+
case 'storageDone':
|
|
204
|
+
// Set cache after successful completion
|
|
205
|
+
this.#cache.set(cacheKey, results);
|
|
206
|
+
resolve(results);
|
|
207
|
+
break;
|
|
208
|
+
case 'storageError':
|
|
209
|
+
reject(new DedotError(event.error));
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}, blockHash).catch(reject);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Clears the internal cache used for storing archive query results.
|
|
217
|
+
* This can be useful for memory management or when you want to force fresh data retrieval.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* // Clear all cached results
|
|
222
|
+
* archive.clearCache();
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
clearCache() {
|
|
226
|
+
this.#cache.clear();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -2,6 +2,7 @@ import { BlockHash, Option } from '@dedot/codecs';
|
|
|
2
2
|
import type { ChainHeadRuntimeVersion, OperationId, StorageQuery, StorageResult } from '@dedot/types/json-rpc';
|
|
3
3
|
import { Deferred, HexString } from '@dedot/utils';
|
|
4
4
|
import type { IJsonRpcClient } from '../../../types.js';
|
|
5
|
+
import { Archive } from '../Archive.js';
|
|
5
6
|
import { JsonRpcGroup, type JsonRpcGroupOptions } from '../JsonRpcGroup.js';
|
|
6
7
|
export type OperationHandler<T = any> = {
|
|
7
8
|
operationId: OperationId;
|
|
@@ -20,6 +21,15 @@ export declare const MIN_FINALIZED_QUEUE_SIZE = 10;
|
|
|
20
21
|
export declare class ChainHead extends JsonRpcGroup<ChainHeadEvent> {
|
|
21
22
|
#private;
|
|
22
23
|
constructor(client: IJsonRpcClient, options?: Partial<JsonRpcGroupOptions>);
|
|
24
|
+
/**
|
|
25
|
+
* Attach an Archive instance as fallback for operations that fail due to unpinned blocks.
|
|
26
|
+
* When a ChainHeadBlockNotPinnedError occurs, the operation will automatically fallback
|
|
27
|
+
* to the Archive API to attempt to retrieve the data from historical blocks.
|
|
28
|
+
*
|
|
29
|
+
* @param archive - Archive instance to use as fallback
|
|
30
|
+
* @returns this ChainHead instance for method chaining
|
|
31
|
+
*/
|
|
32
|
+
withArchive(archive: Archive): this;
|
|
23
33
|
runtimeVersion(): Promise<ChainHeadRuntimeVersion>;
|
|
24
34
|
bestRuntimeVersion(): Promise<ChainHeadRuntimeVersion>;
|
|
25
35
|
finalizedHash(): Promise<BlockHash>;
|
|
@@ -67,4 +77,15 @@ export declare class ChainHead extends JsonRpcGroup<ChainHeadEvent> {
|
|
|
67
77
|
* @protected
|
|
68
78
|
*/
|
|
69
79
|
protected unpin(hashes: BlockHash | BlockHash[]): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Clears the internal cache used for storing query results (both chainHead & archive instances)
|
|
82
|
+
* This can be useful for memory management or when you want to force fresh data retrieval.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* // Clear all cached results
|
|
87
|
+
* chainHead.clearCache();
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
clearCache(): void;
|
|
70
91
|
}
|