@dedot/api 0.14.1 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/chaintypes/substrate/index.d.ts +2 -0
  2. package/chaintypes/substrate/runtime.d.ts +7 -7
  3. package/chaintypes/substrate/types.d.ts +10 -4
  4. package/chaintypes/substrate/view-functions.d.ts +3 -0
  5. package/chaintypes/substrate/view-functions.js +2 -0
  6. package/cjs/chaintypes/substrate/view-functions.js +3 -0
  7. package/cjs/client/BaseSubstrateClient.js +8 -5
  8. package/cjs/client/DedotClient.js +6 -0
  9. package/cjs/client/LegacyClient.js +3 -0
  10. package/cjs/executor/Executor.js +7 -0
  11. package/cjs/executor/RuntimeApiExecutor.js +0 -7
  12. package/cjs/executor/ViewFunctionExecutor.js +78 -0
  13. package/cjs/executor/index.js +2 -0
  14. package/cjs/executor/v2/ViewFunctionExecutorV2.js +21 -0
  15. package/cjs/proxychain.js +5 -6
  16. package/client/BaseSubstrateClient.d.ts +1 -0
  17. package/client/BaseSubstrateClient.js +8 -5
  18. package/client/DedotClient.d.ts +1 -0
  19. package/client/DedotClient.js +7 -1
  20. package/client/LegacyClient.d.ts +1 -0
  21. package/client/LegacyClient.js +4 -1
  22. package/executor/Executor.d.ts +9 -2
  23. package/executor/Executor.js +7 -0
  24. package/executor/RuntimeApiExecutor.d.ts +0 -8
  25. package/executor/RuntimeApiExecutor.js +0 -7
  26. package/executor/ViewFunctionExecutor.d.ts +10 -0
  27. package/executor/ViewFunctionExecutor.js +51 -0
  28. package/executor/index.d.ts +2 -0
  29. package/executor/index.js +2 -0
  30. package/executor/v2/RuntimeApiExecutorV2.d.ts +2 -1
  31. package/executor/v2/ViewFunctionExecutorV2.d.ts +14 -0
  32. package/executor/v2/ViewFunctionExecutorV2.js +17 -0
  33. package/package.json +9 -9
  34. package/proxychain.js +5 -6
  35. package/types.d.ts +1 -0
@@ -6,6 +6,7 @@ import { ChainJsonRpcApis } from './json-rpc.js';
6
6
  import { ChainStorage } from './query.js';
7
7
  import { RuntimeApis } from './runtime.js';
8
8
  import { ChainTx } from './tx.js';
9
+ import { ChainViewFunctions } from './view-functions.js';
9
10
  export * from './types.js';
10
11
  export interface VersionedSubstrateApi<Rv extends RpcVersion> extends GenericSubstrateApi<Rv> {
11
12
  rpc: ChainJsonRpcApis<Rv>;
@@ -14,6 +15,7 @@ export interface VersionedSubstrateApi<Rv extends RpcVersion> extends GenericSub
14
15
  errors: ChainErrors<Rv>;
15
16
  events: ChainEvents<Rv>;
16
17
  call: RuntimeApis<Rv>;
18
+ view: ChainViewFunctions<Rv>;
17
19
  tx: ChainTx<Rv>;
18
20
  }
19
21
  /**
@@ -1,6 +1,6 @@
1
1
  import type { AccountId32, AccountId32Like, Bytes, BytesLike, DispatchError, FixedBytes, H160, H256, Header, Result, RuntimeVersion, U256, UncheckedExtrinsic, UncheckedExtrinsicLike } from '@dedot/codecs';
2
2
  import type { GenericRuntimeApiMethod, GenericRuntimeApis, RpcVersion } from '@dedot/types';
3
- import type { FrameSupportTokensFungibleUnionOfNativeOrWithId, FrameSupportViewFunctionsViewFunctionDispatchError, FrameSupportViewFunctionsViewFunctionId, KitchensinkRuntimeRuntimeCallLike, PalletContractsPrimitivesCode, PalletContractsPrimitivesCodeUploadReturnValue, PalletContractsPrimitivesContractAccessError, PalletContractsPrimitivesContractResult, PalletContractsPrimitivesContractResultResult, PalletContractsWasmDeterminism, PalletReviveEvmApiDebugRpcTypesCallTrace, PalletReviveEvmApiDebugRpcTypesTracerConfig, PalletReviveEvmApiRpcTypesGenGenericTransaction, PalletRevivePrimitivesCode, PalletRevivePrimitivesCodeUploadReturnValue, PalletRevivePrimitivesContractAccessError, PalletRevivePrimitivesContractResult, PalletRevivePrimitivesContractResultInstantiateReturnValue, PalletRevivePrimitivesEthTransactError, PalletRevivePrimitivesEthTransactInfo, PalletTransactionPaymentFeeDetails, PalletTransactionPaymentRuntimeDispatchInfo, SpAuthorityDiscoveryAppPublic, SpConsensusBabeAppPublic, SpConsensusBabeBabeConfiguration, SpConsensusBabeEpoch, SpConsensusBabeOpaqueKeyOwnershipProof, SpConsensusBeefyDoubleVotingProof, SpConsensusBeefyEcdsaCryptoPublic, SpConsensusBeefyForkVotingProofOpaqueValue, SpConsensusBeefyFutureBlockVotingProof, SpConsensusBeefyValidatorSet, SpConsensusGrandpaAppPublic, SpConsensusGrandpaEquivocationProof, SpConsensusSlotsEquivocationProof, SpConsensusSlotsSlot, SpCoreCryptoKeyTypeId, SpCoreOpaqueMetadata, SpInherentsCheckInherentsResult, SpInherentsInherentData, SpMixnetMixnode, SpMixnetMixnodesErr, SpMixnetSessionStatus, SpMmrPrimitivesEncodableOpaqueLeaf, SpMmrPrimitivesError, SpMmrPrimitivesLeafProof, SpRuntimeBlock, SpRuntimeExtrinsicInclusionMode, SpRuntimeOpaqueValue, SpRuntimeTransactionValidityTransactionSource, SpRuntimeTransactionValidityTransactionValidityError, SpRuntimeTransactionValidityValidTransaction, SpStatementStoreRuntimeApiInvalidStatement, SpStatementStoreRuntimeApiStatementSource, SpStatementStoreRuntimeApiValidStatement, SpStatementStoreStatement, SpWeightsWeightV2Weight } from './types.js';
3
+ import type { FrameSupportTokensFungibleUnionOfNativeOrWithId, FrameSupportViewFunctionsViewFunctionDispatchError, FrameSupportViewFunctionsViewFunctionId, KitchensinkRuntimeRuntimeCallLike, PalletContractsPrimitivesCode, PalletContractsPrimitivesCodeUploadReturnValue, PalletContractsPrimitivesContractAccessError, PalletContractsPrimitivesContractResult, PalletContractsPrimitivesContractResultResult, PalletContractsWasmDeterminism, PalletReviveEvmApiDebugRpcTypesTrace, PalletReviveEvmApiDebugRpcTypesTracerType, PalletReviveEvmApiRpcTypesGenGenericTransaction, PalletRevivePrimitivesCode, PalletRevivePrimitivesCodeUploadReturnValue, PalletRevivePrimitivesContractAccessError, PalletRevivePrimitivesContractResult, PalletRevivePrimitivesContractResultInstantiateReturnValue, PalletRevivePrimitivesEthTransactError, PalletRevivePrimitivesEthTransactInfo, PalletTransactionPaymentFeeDetails, PalletTransactionPaymentRuntimeDispatchInfo, SpAuthorityDiscoveryAppPublic, SpConsensusBabeAppPublic, SpConsensusBabeBabeConfiguration, SpConsensusBabeEpoch, SpConsensusBabeOpaqueKeyOwnershipProof, SpConsensusBeefyDoubleVotingProof, SpConsensusBeefyEcdsaCryptoPublic, SpConsensusBeefyForkVotingProofOpaqueValue, SpConsensusBeefyFutureBlockVotingProof, SpConsensusBeefyValidatorSet, SpConsensusGrandpaAppPublic, SpConsensusGrandpaEquivocationProof, SpConsensusSlotsEquivocationProof, SpConsensusSlotsSlot, SpCoreCryptoKeyTypeId, SpCoreOpaqueMetadata, SpInherentsCheckInherentsResult, SpInherentsInherentData, SpMixnetMixnode, SpMixnetMixnodesErr, SpMixnetSessionStatus, SpMmrPrimitivesEncodableOpaqueLeaf, SpMmrPrimitivesError, SpMmrPrimitivesLeafProof, SpRuntimeBlock, SpRuntimeExtrinsicInclusionMode, SpRuntimeOpaqueValue, SpRuntimeTransactionValidityTransactionSource, SpRuntimeTransactionValidityTransactionValidityError, SpRuntimeTransactionValidityValidTransaction, SpStatementStoreRuntimeApiInvalidStatement, SpStatementStoreRuntimeApiStatementSource, SpStatementStoreRuntimeApiValidStatement, SpStatementStoreStatement, SpWeightsWeightV2Weight } from './types.js';
4
4
  export interface RuntimeApis<Rv extends RpcVersion> extends GenericRuntimeApis<Rv> {
5
5
  /**
6
6
  * @runtimeapi: Core - 0xdf6acb689907609b
@@ -645,9 +645,9 @@ export interface RuntimeApis<Rv extends RpcVersion> extends GenericRuntimeApis<R
645
645
  *
646
646
  * @callname: ReviveApi_trace_block
647
647
  * @param {SpRuntimeBlock} block
648
- * @param {PalletReviveEvmApiDebugRpcTypesTracerConfig} config
648
+ * @param {PalletReviveEvmApiDebugRpcTypesTracerType} config
649
649
  **/
650
- traceBlock: GenericRuntimeApiMethod<Rv, (block: SpRuntimeBlock, config: PalletReviveEvmApiDebugRpcTypesTracerConfig) => Promise<Array<[number, PalletReviveEvmApiDebugRpcTypesCallTrace]>>>;
650
+ traceBlock: GenericRuntimeApiMethod<Rv, (block: SpRuntimeBlock, config: PalletReviveEvmApiDebugRpcTypesTracerType) => Promise<Array<[number, PalletReviveEvmApiDebugRpcTypesTrace]>>>;
651
651
  /**
652
652
  * Traces the execution of a specific transaction within a block.
653
653
  *
@@ -659,9 +659,9 @@ export interface RuntimeApis<Rv extends RpcVersion> extends GenericRuntimeApis<R
659
659
  * @callname: ReviveApi_trace_tx
660
660
  * @param {SpRuntimeBlock} block
661
661
  * @param {number} tx_index
662
- * @param {PalletReviveEvmApiDebugRpcTypesTracerConfig} config
662
+ * @param {PalletReviveEvmApiDebugRpcTypesTracerType} config
663
663
  **/
664
- traceTx: GenericRuntimeApiMethod<Rv, (block: SpRuntimeBlock, txIndex: number, config: PalletReviveEvmApiDebugRpcTypesTracerConfig) => Promise<PalletReviveEvmApiDebugRpcTypesCallTrace | undefined>>;
664
+ traceTx: GenericRuntimeApiMethod<Rv, (block: SpRuntimeBlock, txIndex: number, config: PalletReviveEvmApiDebugRpcTypesTracerType) => Promise<PalletReviveEvmApiDebugRpcTypesTrace | undefined>>;
665
665
  /**
666
666
  * Dry run and return the trace of the given call.
667
667
  *
@@ -669,9 +669,9 @@ export interface RuntimeApis<Rv extends RpcVersion> extends GenericRuntimeApis<R
669
669
  *
670
670
  * @callname: ReviveApi_trace_call
671
671
  * @param {PalletReviveEvmApiRpcTypesGenGenericTransaction} tx
672
- * @param {PalletReviveEvmApiDebugRpcTypesTracerConfig} config
672
+ * @param {PalletReviveEvmApiDebugRpcTypesTracerType} config
673
673
  **/
674
- traceCall: GenericRuntimeApiMethod<Rv, (tx: PalletReviveEvmApiRpcTypesGenGenericTransaction, config: PalletReviveEvmApiDebugRpcTypesTracerConfig) => Promise<Result<PalletReviveEvmApiDebugRpcTypesCallTrace, PalletRevivePrimitivesEthTransactError>>>;
674
+ traceCall: GenericRuntimeApiMethod<Rv, (tx: PalletReviveEvmApiRpcTypesGenGenericTransaction, config: PalletReviveEvmApiDebugRpcTypesTracerType) => Promise<Result<PalletReviveEvmApiDebugRpcTypesTrace, PalletRevivePrimitivesEthTransactError>>>;
675
675
  /**
676
676
  * Generic runtime api call
677
677
  **/
@@ -33461,11 +33461,17 @@ export type PalletRevivePrimitivesCodeUploadReturnValue = {
33461
33461
  deposit: bigint;
33462
33462
  };
33463
33463
  export type PalletRevivePrimitivesContractAccessError = 'DoesntExist' | 'KeyDecodingFailed';
33464
- export type PalletReviveEvmApiDebugRpcTypesTracerConfig = {
33464
+ export type PalletReviveEvmApiDebugRpcTypesTracerType = {
33465
33465
  type: 'CallTracer';
33466
- value: {
33467
- withLogs: boolean;
33468
- };
33466
+ value?: PalletReviveEvmApiDebugRpcTypesCallTracerConfig | undefined;
33467
+ };
33468
+ export type PalletReviveEvmApiDebugRpcTypesCallTracerConfig = {
33469
+ withLogs: boolean;
33470
+ onlyTopCall: boolean;
33471
+ };
33472
+ export type PalletReviveEvmApiDebugRpcTypesTrace = {
33473
+ type: 'Call';
33474
+ value: PalletReviveEvmApiDebugRpcTypesCallTrace;
33469
33475
  };
33470
33476
  export type PalletReviveEvmApiDebugRpcTypesCallTrace = {
33471
33477
  from: H160;
@@ -0,0 +1,3 @@
1
+ import type { GenericChainViewFunctions, RpcVersion } from '@dedot/types';
2
+ export interface ChainViewFunctions<Rv extends RpcVersion> extends GenericChainViewFunctions<Rv> {
3
+ }
@@ -0,0 +1,2 @@
1
+ // Generated by dedot cli
2
+ export {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // Generated by dedot cli
3
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -8,7 +8,7 @@ const index_js_1 = require("../executor/index.js");
8
8
  const index_js_2 = require("../json-rpc/index.js");
9
9
  const proxychain_js_1 = require("../proxychain.js");
10
10
  const index_js_3 = require("../storage/index.js");
11
- const SUPPORTED_METADATA_VERSIONS = [15, 14];
11
+ const SUPPORTED_METADATA_VERSIONS = [16, 15, 14];
12
12
  const MetadataApiHash = (0, utils_1.calcRuntimeApiHash)('Metadata'); // 0x37e397fc7c91f5e4
13
13
  const MESSAGE = 'Make sure to call `.connect()` method first before using the API interfaces.';
14
14
  function ensurePresence(value) {
@@ -163,10 +163,10 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
163
163
  // If there is no runtime, we assume that the node supports Metadata Api V2
164
164
  const supportedV2 = runtime ? runtime.apis[MetadataApiHash] === 2 : true;
165
165
  if (supportedV2) {
166
- // It makes sense to call metadata.metadataVersions to fetch the list of supported metadata versions first
167
- // But for now, this approach could potentially help save/reduce one rpc call to the server in case the node support v15
168
- // Question: Why not having a `metadata.metadataLatest` to fetch the latest version?
169
- for (const version of SUPPORTED_METADATA_VERSIONS) {
166
+ const versions = (await this.callAt(hash).metadata.metadataVersions()) // --
167
+ .filter((v) => SUPPORTED_METADATA_VERSIONS.includes(v))
168
+ .sort((a, b) => b - a); // sort desc, bigger first
169
+ for (const version of versions) {
170
170
  try {
171
171
  const rawMetadata = await this.callAt(hash).metadata.metadataAtVersion(version);
172
172
  if (!rawMetadata)
@@ -297,6 +297,9 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
297
297
  get query() {
298
298
  throw new Error('Unimplemented!');
299
299
  }
300
+ get view() {
301
+ throw new Error('Unimplemented!');
302
+ }
300
303
  get call() {
301
304
  return this.callAt();
302
305
  }
@@ -141,6 +141,11 @@ class DedotClient// prettier-end-here
141
141
  executor: new index_js_1.StorageQueryExecutorV2(this, this.chainHead),
142
142
  });
143
143
  }
144
+ get view() {
145
+ return (0, proxychain_js_1.newProxyChain)({
146
+ executor: new index_js_1.ViewFunctionExecutorV2(this, this.chainHead),
147
+ });
148
+ }
144
149
  get call() {
145
150
  return this.callAt();
146
151
  }
@@ -189,6 +194,7 @@ class DedotClient// prettier-end-here
189
194
  api.errors = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ErrorExecutor(api) });
190
195
  api.query = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.StorageQueryExecutorV2(api, this.chainHead) });
191
196
  api.call = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.RuntimeApiExecutorV2(api, this.chainHead) });
197
+ api.view = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ViewFunctionExecutorV2(api, this.chainHead) });
192
198
  this.#apiAtCache[hash] = api;
193
199
  return api;
194
200
  }
@@ -208,6 +208,9 @@ class LegacyClient// prettier-end-here
208
208
  callAt(hash) {
209
209
  return (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.RuntimeApiExecutor(this, hash) });
210
210
  }
211
+ get view() {
212
+ return (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ViewFunctionExecutor(this) });
213
+ }
211
214
  /**
212
215
  * @description Entry-point for executing on-chain transactions
213
216
  *
@@ -27,6 +27,13 @@ class Executor {
27
27
  (0, utils_1.assert)(targetPallet, new utils_1.UnknownApiError(`Pallet not found: ${name}`));
28
28
  return targetPallet;
29
29
  }
30
+ stateCall(callParams) {
31
+ const { func, params, at } = callParams;
32
+ const args = [func, params];
33
+ if (at)
34
+ args.push(at);
35
+ return this.client.rpc.state_call(...args);
36
+ }
30
37
  execute(...paths) {
31
38
  try {
32
39
  return this.doExecute(...paths);
@@ -35,13 +35,6 @@ class RuntimeApiExecutor extends Executor_js_1.Executor {
35
35
  callFn.meta = callSpec;
36
36
  return callFn;
37
37
  }
38
- stateCall(callParams) {
39
- const { func, params, at } = callParams;
40
- const args = [func, params];
41
- if (at)
42
- args.push(at);
43
- return this.client.rpc.state_call(...args);
44
- }
45
38
  tryDecode(callSpec, raw) {
46
39
  const $codec = this.#findCodec(callSpec, `Codec not found to decode respond data for ${this.#callName(callSpec)}`);
47
40
  return $codec.tryDecode(raw);
@@ -0,0 +1,78 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.ViewFunctionExecutor = void 0;
27
+ const $ = __importStar(require("@dedot/shape"));
28
+ const utils_1 = require("@dedot/utils");
29
+ const Executor_js_1 = require("./Executor.js");
30
+ const RUNTIME_API_NAME = 'RuntimeViewFunction';
31
+ const METHOD_NAME = 'execute_view_function';
32
+ /**
33
+ * @name ViewFunctionExecutor
34
+ * @description Execute view functions using the runtimeViewFunction API
35
+ */
36
+ class ViewFunctionExecutor extends Executor_js_1.Executor {
37
+ doExecute(pallet, viewFunction) {
38
+ const targetPallet = this.getPallet(pallet);
39
+ const viewFunctionDef = this.#findViewFunctionDef(targetPallet, viewFunction);
40
+ (0, utils_1.assert)(viewFunctionDef, new utils_1.UnknownApiError(`View function not found: ${pallet}.${viewFunction}`));
41
+ const callFn = async (...args) => {
42
+ const { inputs, id, output } = viewFunctionDef;
43
+ const formattedInputs = inputs.map(({ typeId }, index) => this.registry.findCodec(typeId).tryEncode(args[index]));
44
+ const bytes = (0, utils_1.u8aToHex)((0, utils_1.concatU8a)(id, $.Vec($.u8).tryEncode((0, utils_1.concatU8a)(...formattedInputs))));
45
+ const func = `${RUNTIME_API_NAME}_${METHOD_NAME}`;
46
+ const callParams = {
47
+ func,
48
+ params: bytes,
49
+ at: this.atBlockHash,
50
+ };
51
+ const rawResult = await this.stateCall(callParams);
52
+ const result = this.#decodeRawResult(rawResult);
53
+ if (result.isErr) {
54
+ throw new utils_1.DedotError(`Error when calling view function (type: ${result.err.type})`);
55
+ }
56
+ return this.registry.findCodec(output).tryDecode(result.value);
57
+ };
58
+ callFn.meta = {
59
+ ...viewFunctionDef,
60
+ pallet: targetPallet.name,
61
+ palletIndex: targetPallet.index,
62
+ };
63
+ return callFn;
64
+ }
65
+ #findViewFunctionDef(pallet, viewFunctionName) {
66
+ return pallet.viewFunctions.find((vf) => (0, utils_1.stringCamelCase)(vf.name) === viewFunctionName);
67
+ }
68
+ #decodeRawResult(rawResult) {
69
+ const runtimeViewFunctionDef = this.metadata.apis
70
+ .find((api) => api.name === RUNTIME_API_NAME)
71
+ ?.methods.find((method) => method.name === METHOD_NAME);
72
+ (0, utils_1.assert)(runtimeViewFunctionDef, new utils_1.UnknownApiError('RuntimeViewFunction definition not found'));
73
+ const $codec = this.registry.findCodec(runtimeViewFunctionDef.output);
74
+ const result = $codec.tryDecode(rawResult);
75
+ return result;
76
+ }
77
+ }
78
+ exports.ViewFunctionExecutor = ViewFunctionExecutor;
@@ -22,6 +22,8 @@ __exportStar(require("./ErrorExecutor.js"), exports);
22
22
  __exportStar(require("./EventExecutor.js"), exports);
23
23
  __exportStar(require("./RuntimeApiExecutor.js"), exports);
24
24
  __exportStar(require("./TxExecutor.js"), exports);
25
+ __exportStar(require("./ViewFunctionExecutor.js"), exports);
25
26
  __exportStar(require("./v2/StorageQueryExecutorV2.js"), exports);
26
27
  __exportStar(require("./v2/RuntimeApiExecutorV2.js"), exports);
27
28
  __exportStar(require("./v2/TxExecutorV2.js"), exports);
29
+ __exportStar(require("./v2/ViewFunctionExecutorV2.js"), exports);
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ViewFunctionExecutorV2 = void 0;
4
+ const utils_1 = require("@dedot/utils");
5
+ const ViewFunctionExecutor_js_1 = require("../ViewFunctionExecutor.js");
6
+ /**
7
+ * @name ViewFunctionExecutorV2
8
+ */
9
+ class ViewFunctionExecutorV2 extends ViewFunctionExecutor_js_1.ViewFunctionExecutor {
10
+ chainHead;
11
+ constructor(client, chainHead) {
12
+ (0, utils_1.assert)(client.rpcVersion === 'v2', 'Only supports JSON-RPC v2');
13
+ super(client);
14
+ this.chainHead = chainHead;
15
+ }
16
+ stateCall(callParams) {
17
+ const { func, params, at } = callParams;
18
+ return this.chainHead.call(func, params, at);
19
+ }
20
+ }
21
+ exports.ViewFunctionExecutorV2 = ViewFunctionExecutorV2;
package/cjs/proxychain.js CHANGED
@@ -15,12 +15,11 @@ const newProxyChain = (carrier, currentLevel = 1, maxLevel = 3) => {
15
15
  }
16
16
  return new Proxy(carrier, {
17
17
  get(target, property, receiver) {
18
- if (!target.chain) {
19
- target.chain = [];
20
- }
21
- const { chain } = target;
22
- chain.push(property.toString());
23
- return (0, exports.newProxyChain)(target, currentLevel + 1, maxLevel);
18
+ const newCarrier = {
19
+ executor: target.executor,
20
+ chain: [...(target.chain || []), property.toString()],
21
+ };
22
+ return (0, exports.newProxyChain)(newCarrier, currentLevel + 1, maxLevel);
24
23
  },
25
24
  });
26
25
  };
@@ -69,6 +69,7 @@ export declare abstract class BaseSubstrateClient<Rv extends RpcVersion, ChainAp
69
69
  get errors(): ChainApi[Rv]['errors'];
70
70
  get events(): ChainApi[Rv]['events'];
71
71
  get query(): ChainApi[Rv]['query'];
72
+ get view(): ChainApi[Rv]['view'];
72
73
  get call(): ChainApi[Rv]['call'];
73
74
  protected callAt(hash?: BlockHash): ChainApi[Rv]['call'];
74
75
  get tx(): ChainApi[Rv]['tx'];
@@ -5,7 +5,7 @@ import { ConstantExecutor, ErrorExecutor, EventExecutor } from '../executor/inde
5
5
  import { isJsonRpcProvider, JsonRpcClient } from '../json-rpc/index.js';
6
6
  import { newProxyChain } from '../proxychain.js';
7
7
  import { QueryableStorage } from '../storage/index.js';
8
- const SUPPORTED_METADATA_VERSIONS = [15, 14];
8
+ const SUPPORTED_METADATA_VERSIONS = [16, 15, 14];
9
9
  const MetadataApiHash = calcRuntimeApiHash('Metadata'); // 0x37e397fc7c91f5e4
10
10
  const MESSAGE = 'Make sure to call `.connect()` method first before using the API interfaces.';
11
11
  export function ensurePresence(value) {
@@ -159,10 +159,10 @@ export class BaseSubstrateClient extends JsonRpcClient {
159
159
  // If there is no runtime, we assume that the node supports Metadata Api V2
160
160
  const supportedV2 = runtime ? runtime.apis[MetadataApiHash] === 2 : true;
161
161
  if (supportedV2) {
162
- // It makes sense to call metadata.metadataVersions to fetch the list of supported metadata versions first
163
- // But for now, this approach could potentially help save/reduce one rpc call to the server in case the node support v15
164
- // Question: Why not having a `metadata.metadataLatest` to fetch the latest version?
165
- for (const version of SUPPORTED_METADATA_VERSIONS) {
162
+ const versions = (await this.callAt(hash).metadata.metadataVersions()) // --
163
+ .filter((v) => SUPPORTED_METADATA_VERSIONS.includes(v))
164
+ .sort((a, b) => b - a); // sort desc, bigger first
165
+ for (const version of versions) {
166
166
  try {
167
167
  const rawMetadata = await this.callAt(hash).metadata.metadataAtVersion(version);
168
168
  if (!rawMetadata)
@@ -293,6 +293,9 @@ export class BaseSubstrateClient extends JsonRpcClient {
293
293
  get query() {
294
294
  throw new Error('Unimplemented!');
295
295
  }
296
+ get view() {
297
+ throw new Error('Unimplemented!');
298
+ }
296
299
  get call() {
297
300
  return this.callAt();
298
301
  }
@@ -49,6 +49,7 @@ export declare class DedotClient<ChainApi extends VersionedGenericSubstrateApi =
49
49
  protected onDisconnected: () => Promise<void>;
50
50
  protected cleanUp(): void;
51
51
  get query(): ChainApi[RpcV2]['query'];
52
+ get view(): ChainApi[RpcV2]['view'];
52
53
  get call(): ChainApi[RpcV2]['call'];
53
54
  protected callAt(blockHash?: BlockHash): ChainApi[RpcV2]['call'];
54
55
  get tx(): ChainApi[RpcV2]['tx'];
@@ -1,7 +1,7 @@
1
1
  import { $H256, PortableRegistry } from '@dedot/codecs';
2
2
  import { u32 } from '@dedot/shape';
3
3
  import { assert, concatU8a, noop, twox64Concat, u8aToHex, xxhashAsU8a } from '@dedot/utils';
4
- import { ConstantExecutor, ErrorExecutor, EventExecutor, RuntimeApiExecutorV2, StorageQueryExecutorV2, TxExecutorV2, } from '../executor/index.js';
4
+ import { ConstantExecutor, ErrorExecutor, EventExecutor, RuntimeApiExecutorV2, StorageQueryExecutorV2, ViewFunctionExecutorV2, TxExecutorV2, } from '../executor/index.js';
5
5
  import { ChainHead, ChainSpec, Transaction, TransactionWatch } from '../json-rpc/index.js';
6
6
  import { newProxyChain } from '../proxychain.js';
7
7
  import { NewStorageQuery } from '../storage/index.js';
@@ -138,6 +138,11 @@ export class DedotClient// prettier-end-here
138
138
  executor: new StorageQueryExecutorV2(this, this.chainHead),
139
139
  });
140
140
  }
141
+ get view() {
142
+ return newProxyChain({
143
+ executor: new ViewFunctionExecutorV2(this, this.chainHead),
144
+ });
145
+ }
141
146
  get call() {
142
147
  return this.callAt();
143
148
  }
@@ -186,6 +191,7 @@ export class DedotClient// prettier-end-here
186
191
  api.errors = newProxyChain({ executor: new ErrorExecutor(api) });
187
192
  api.query = newProxyChain({ executor: new StorageQueryExecutorV2(api, this.chainHead) });
188
193
  api.call = newProxyChain({ executor: new RuntimeApiExecutorV2(api, this.chainHead) });
194
+ api.view = newProxyChain({ executor: new ViewFunctionExecutorV2(api, this.chainHead) });
189
195
  this.#apiAtCache[hash] = api;
190
196
  return api;
191
197
  }
@@ -111,6 +111,7 @@ export declare class LegacyClient<ChainApi extends VersionedGenericSubstrateApi
111
111
  */
112
112
  get call(): ChainApi[RpcLegacy]['call'];
113
113
  protected callAt(hash?: BlockHash): ChainApi[RpcLegacy]['call'];
114
+ get view(): ChainApi[RpcLegacy]['view'];
114
115
  /**
115
116
  * @description Entry-point for executing on-chain transactions
116
117
  *
@@ -1,5 +1,5 @@
1
1
  import { PortableRegistry } from '@dedot/codecs';
2
- import { ConstantExecutor, ErrorExecutor, EventExecutor, RuntimeApiExecutor, StorageQueryExecutor, TxExecutor, } from '../executor/index.js';
2
+ import { ConstantExecutor, ErrorExecutor, EventExecutor, RuntimeApiExecutor, StorageQueryExecutor, TxExecutor, ViewFunctionExecutor, } from '../executor/index.js';
3
3
  import { newProxyChain } from '../proxychain.js';
4
4
  import { LegacyStorageQuery } from '../storage/index.js';
5
5
  import { BaseSubstrateClient } from './BaseSubstrateClient.js';
@@ -205,6 +205,9 @@ export class LegacyClient// prettier-end-here
205
205
  callAt(hash) {
206
206
  return newProxyChain({ executor: new RuntimeApiExecutor(this, hash) });
207
207
  }
208
+ get view() {
209
+ return newProxyChain({ executor: new ViewFunctionExecutor(this) });
210
+ }
208
211
  /**
209
212
  * @description Entry-point for executing on-chain transactions
210
213
  *
@@ -1,6 +1,12 @@
1
1
  import type { BlockHash, PalletDefLatest } from '@dedot/codecs';
2
2
  import type { GenericSubstrateApi } from '@dedot/types';
3
+ import { HexString } from '@dedot/utils';
3
4
  import { ISubstrateClientAt } from '../types.js';
5
+ export interface StateCallParams {
6
+ func: string;
7
+ params: HexString;
8
+ at?: BlockHash;
9
+ }
4
10
  /**
5
11
  * @name Executor
6
12
  * @description Execution abstraction for a specific action
@@ -163,7 +169,7 @@ export declare abstract class Executor<ChainApi extends GenericSubstrateApi = Ge
163
169
  docs: string[];
164
170
  }[];
165
171
  viewFunctions: {
166
- id: readonly [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
172
+ id: Uint8Array;
167
173
  name: string;
168
174
  inputs: {
169
175
  name: string;
@@ -200,8 +206,8 @@ export declare abstract class Executor<ChainApi extends GenericSubstrateApi = Ge
200
206
  extrinsic: {
201
207
  versions: number[];
202
208
  addressTypeId: number;
203
- signatureTypeId: number;
204
209
  callTypeId: number;
210
+ signatureTypeId: number;
205
211
  signedExtensionsByVersion: ReadonlyMap<number, number[]>;
206
212
  signedExtensions: {
207
213
  ident: string;
@@ -258,6 +264,7 @@ export declare abstract class Executor<ChainApi extends GenericSubstrateApi = Ge
258
264
  };
259
265
  };
260
266
  getPallet(name: string): PalletDefLatest;
267
+ protected stateCall(callParams: StateCallParams): Promise<HexString>;
261
268
  execute(...paths: string[]): unknown;
262
269
  abstract doExecute(...paths: string[]): unknown;
263
270
  }
@@ -24,6 +24,13 @@ export class Executor {
24
24
  assert(targetPallet, new UnknownApiError(`Pallet not found: ${name}`));
25
25
  return targetPallet;
26
26
  }
27
+ stateCall(callParams) {
28
+ const { func, params, at } = callParams;
29
+ const args = [func, params];
30
+ if (at)
31
+ args.push(at);
32
+ return this.client.rpc.state_call(...args);
33
+ }
27
34
  execute(...paths) {
28
35
  try {
29
36
  return this.doExecute(...paths);
@@ -1,16 +1,9 @@
1
- import { BlockHash } from '@dedot/codecs';
2
1
  import type { GenericRuntimeApiMethod, GenericSubstrateApi, RuntimeApiMethodParamSpec, RuntimeApiMethodSpec, RuntimeApiSpec } from '@dedot/types';
3
- import { HexString } from '@dedot/utils';
4
2
  import { Executor } from './Executor.js';
5
3
  export declare const FallbackRuntimeApis: Record<string, number>;
6
4
  export declare const FallbackRuntimeApiSpecs: {
7
5
  Metadata: RuntimeApiSpec[];
8
6
  };
9
- export interface StateCallParams {
10
- func: string;
11
- params: HexString;
12
- at?: BlockHash;
13
- }
14
7
  /**
15
8
  * @name RuntimeApiExecutor
16
9
  * @description Execute a runtime api call,
@@ -21,7 +14,6 @@ export interface StateCallParams {
21
14
  export declare class RuntimeApiExecutor<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends Executor<ChainApi> {
22
15
  #private;
23
16
  doExecute(runtimeApi: string, method: string): GenericRuntimeApiMethod;
24
- protected stateCall(callParams: StateCallParams): Promise<HexString>;
25
17
  tryDecode(callSpec: RuntimeApiMethodSpec, raw: any): unknown;
26
18
  tryEncode(paramSpec: RuntimeApiMethodParamSpec, value: any): Uint8Array;
27
19
  }
@@ -32,13 +32,6 @@ export class RuntimeApiExecutor extends Executor {
32
32
  callFn.meta = callSpec;
33
33
  return callFn;
34
34
  }
35
- stateCall(callParams) {
36
- const { func, params, at } = callParams;
37
- const args = [func, params];
38
- if (at)
39
- args.push(at);
40
- return this.client.rpc.state_call(...args);
41
- }
42
35
  tryDecode(callSpec, raw) {
43
36
  const $codec = this.#findCodec(callSpec, `Codec not found to decode respond data for ${this.#callName(callSpec)}`);
44
37
  return $codec.tryDecode(raw);
@@ -0,0 +1,10 @@
1
+ import type { GenericSubstrateApi, GenericViewFunction } from '@dedot/types';
2
+ import { Executor } from './Executor.js';
3
+ /**
4
+ * @name ViewFunctionExecutor
5
+ * @description Execute view functions using the runtimeViewFunction API
6
+ */
7
+ export declare class ViewFunctionExecutor<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends Executor<ChainApi> {
8
+ #private;
9
+ doExecute(pallet: string, viewFunction: string): GenericViewFunction;
10
+ }
@@ -0,0 +1,51 @@
1
+ import * as $ from '@dedot/shape';
2
+ import { assert, concatU8a, stringCamelCase, u8aToHex, UnknownApiError, DedotError } from '@dedot/utils';
3
+ import { Executor } from './Executor.js';
4
+ const RUNTIME_API_NAME = 'RuntimeViewFunction';
5
+ const METHOD_NAME = 'execute_view_function';
6
+ /**
7
+ * @name ViewFunctionExecutor
8
+ * @description Execute view functions using the runtimeViewFunction API
9
+ */
10
+ export class ViewFunctionExecutor extends Executor {
11
+ doExecute(pallet, viewFunction) {
12
+ const targetPallet = this.getPallet(pallet);
13
+ const viewFunctionDef = this.#findViewFunctionDef(targetPallet, viewFunction);
14
+ assert(viewFunctionDef, new UnknownApiError(`View function not found: ${pallet}.${viewFunction}`));
15
+ const callFn = async (...args) => {
16
+ const { inputs, id, output } = viewFunctionDef;
17
+ const formattedInputs = inputs.map(({ typeId }, index) => this.registry.findCodec(typeId).tryEncode(args[index]));
18
+ const bytes = u8aToHex(concatU8a(id, $.Vec($.u8).tryEncode(concatU8a(...formattedInputs))));
19
+ const func = `${RUNTIME_API_NAME}_${METHOD_NAME}`;
20
+ const callParams = {
21
+ func,
22
+ params: bytes,
23
+ at: this.atBlockHash,
24
+ };
25
+ const rawResult = await this.stateCall(callParams);
26
+ const result = this.#decodeRawResult(rawResult);
27
+ if (result.isErr) {
28
+ throw new DedotError(`Error when calling view function (type: ${result.err.type})`);
29
+ }
30
+ return this.registry.findCodec(output).tryDecode(result.value);
31
+ };
32
+ callFn.meta = {
33
+ ...viewFunctionDef,
34
+ pallet: targetPallet.name,
35
+ palletIndex: targetPallet.index,
36
+ };
37
+ return callFn;
38
+ }
39
+ #findViewFunctionDef(pallet, viewFunctionName) {
40
+ return pallet.viewFunctions.find((vf) => stringCamelCase(vf.name) === viewFunctionName);
41
+ }
42
+ #decodeRawResult(rawResult) {
43
+ const runtimeViewFunctionDef = this.metadata.apis
44
+ .find((api) => api.name === RUNTIME_API_NAME)
45
+ ?.methods.find((method) => method.name === METHOD_NAME);
46
+ assert(runtimeViewFunctionDef, new UnknownApiError('RuntimeViewFunction definition not found'));
47
+ const $codec = this.registry.findCodec(runtimeViewFunctionDef.output);
48
+ const result = $codec.tryDecode(rawResult);
49
+ return result;
50
+ }
51
+ }
@@ -6,6 +6,8 @@ export * from './ErrorExecutor.js';
6
6
  export * from './EventExecutor.js';
7
7
  export * from './RuntimeApiExecutor.js';
8
8
  export * from './TxExecutor.js';
9
+ export * from './ViewFunctionExecutor.js';
9
10
  export * from './v2/StorageQueryExecutorV2.js';
10
11
  export * from './v2/RuntimeApiExecutorV2.js';
11
12
  export * from './v2/TxExecutorV2.js';
13
+ export * from './v2/ViewFunctionExecutorV2.js';
package/executor/index.js CHANGED
@@ -6,6 +6,8 @@ export * from './ErrorExecutor.js';
6
6
  export * from './EventExecutor.js';
7
7
  export * from './RuntimeApiExecutor.js';
8
8
  export * from './TxExecutor.js';
9
+ export * from './ViewFunctionExecutor.js';
9
10
  export * from './v2/StorageQueryExecutorV2.js';
10
11
  export * from './v2/RuntimeApiExecutorV2.js';
11
12
  export * from './v2/TxExecutorV2.js';
13
+ export * from './v2/ViewFunctionExecutorV2.js';
@@ -3,7 +3,8 @@ import type { GenericSubstrateApi } from '@dedot/types';
3
3
  import { HexString } from '@dedot/utils';
4
4
  import { ChainHead } from '../../json-rpc/index.js';
5
5
  import { ISubstrateClientAt } from '../../types.js';
6
- import { RuntimeApiExecutor, StateCallParams } from '../RuntimeApiExecutor.js';
6
+ import { StateCallParams } from '../Executor.js';
7
+ import { RuntimeApiExecutor } from '../RuntimeApiExecutor.js';
7
8
  /**
8
9
  * @name RuntimeApiExecutorV2
9
10
  */
@@ -0,0 +1,14 @@
1
+ import type { GenericSubstrateApi } from '@dedot/types';
2
+ import { HexString } from '@dedot/utils';
3
+ import { ChainHead } from '../../json-rpc/index.js';
4
+ import { ISubstrateClientAt } from '../../types.js';
5
+ import { StateCallParams } from '../Executor.js';
6
+ import { ViewFunctionExecutor } from '../ViewFunctionExecutor.js';
7
+ /**
8
+ * @name ViewFunctionExecutorV2
9
+ */
10
+ export declare class ViewFunctionExecutorV2<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends ViewFunctionExecutor<ChainApi> {
11
+ chainHead: ChainHead;
12
+ constructor(client: ISubstrateClientAt<ChainApi>, chainHead: ChainHead);
13
+ protected stateCall(callParams: StateCallParams): Promise<HexString>;
14
+ }
@@ -0,0 +1,17 @@
1
+ import { assert } from '@dedot/utils';
2
+ import { ViewFunctionExecutor } from '../ViewFunctionExecutor.js';
3
+ /**
4
+ * @name ViewFunctionExecutorV2
5
+ */
6
+ export class ViewFunctionExecutorV2 extends ViewFunctionExecutor {
7
+ chainHead;
8
+ constructor(client, chainHead) {
9
+ assert(client.rpcVersion === 'v2', 'Only supports JSON-RPC v2');
10
+ super(client);
11
+ this.chainHead = chainHead;
12
+ }
13
+ stateCall(callParams) {
14
+ const { func, params, at } = callParams;
15
+ return this.chainHead.call(func, params, at);
16
+ }
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dedot/api",
3
- "version": "0.14.1",
3
+ "version": "0.15.1",
4
4
  "description": "A delightful JavaScript/TypeScript client for Polkadot & Substrate",
5
5
  "author": "Thang X. Vu <thang@dedot.dev>",
6
6
  "homepage": "https://dedot.dev",
@@ -13,13 +13,13 @@
13
13
  "type": "module",
14
14
  "sideEffects": false,
15
15
  "dependencies": {
16
- "@dedot/codecs": "0.14.1",
17
- "@dedot/providers": "0.14.1",
18
- "@dedot/runtime-specs": "0.14.1",
19
- "@dedot/shape": "0.14.1",
20
- "@dedot/storage": "0.14.1",
21
- "@dedot/types": "0.14.1",
22
- "@dedot/utils": "0.14.1"
16
+ "@dedot/codecs": "0.15.1",
17
+ "@dedot/providers": "0.15.1",
18
+ "@dedot/runtime-specs": "0.15.1",
19
+ "@dedot/shape": "0.15.1",
20
+ "@dedot/storage": "0.15.1",
21
+ "@dedot/types": "0.15.1",
22
+ "@dedot/utils": "0.15.1"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json",
@@ -48,7 +48,7 @@
48
48
  "node": ">=18"
49
49
  },
50
50
  "license": "Apache-2.0",
51
- "gitHead": "d5adec49781a6e0b45910055dcaf9bf472a39a6b",
51
+ "gitHead": "fdac8072dc7ea6698f19f11604904b665ec7ba89",
52
52
  "module": "./index.js",
53
53
  "types": "./index.d.ts"
54
54
  }
package/proxychain.js CHANGED
@@ -12,12 +12,11 @@ export const newProxyChain = (carrier, currentLevel = 1, maxLevel = 3) => {
12
12
  }
13
13
  return new Proxy(carrier, {
14
14
  get(target, property, receiver) {
15
- if (!target.chain) {
16
- target.chain = [];
17
- }
18
- const { chain } = target;
19
- chain.push(property.toString());
20
- return newProxyChain(target, currentLevel + 1, maxLevel);
15
+ const newCarrier = {
16
+ executor: target.executor,
17
+ chain: [...(target.chain || []), property.toString()],
18
+ };
19
+ return newProxyChain(newCarrier, currentLevel + 1, maxLevel);
21
20
  },
22
21
  });
23
22
  };
package/types.d.ts CHANGED
@@ -99,6 +99,7 @@ export interface ISubstrateClientAt<ChainApi extends GenericSubstrateApi = Gener
99
99
  call: ChainApi['call'];
100
100
  events: ChainApi['events'];
101
101
  errors: ChainApi['errors'];
102
+ view: ChainApi['view'];
102
103
  }
103
104
  /**
104
105
  * A generic interface for Substrate clients