@dedot/api 0.7.1 → 0.8.1-next.4880b708.2
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/cjs/client/BaseSubstrateClient.js +32 -1
- package/cjs/executor/StorageQueryExecutor.js +14 -6
- package/cjs/executor/v2/StorageQueryExecutorV2.js +6 -2
- package/cjs/storage/QueryableStorage.js +19 -9
- package/client/BaseSubstrateClient.d.ts +4 -0
- package/client/BaseSubstrateClient.js +32 -1
- package/executor/StorageQueryExecutor.js +15 -7
- package/executor/v2/StorageQueryExecutorV2.js +6 -2
- package/package.json +9 -9
- package/storage/QueryableStorage.d.ts +2 -1
- package/storage/QueryableStorage.js +19 -9
|
@@ -87,13 +87,44 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
if (shouldUpdateCache && this._localCache) {
|
|
90
|
-
|
|
90
|
+
const encodedMetadata = (0, utils_1.u8aToHex)(codecs_1.$Metadata.tryEncode(metadata));
|
|
91
|
+
await this.safeSetMetadataToCache(metadataKey, encodedMetadata);
|
|
91
92
|
}
|
|
92
93
|
if (!metadata) {
|
|
93
94
|
throw new Error('Cannot load metadata');
|
|
94
95
|
}
|
|
95
96
|
this.setMetadata(metadata);
|
|
96
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Safely set metadata to cache with fallback cleanup if storage limit is exceeded
|
|
100
|
+
*/
|
|
101
|
+
async safeSetMetadataToCache(key, value) {
|
|
102
|
+
if (!this._localCache)
|
|
103
|
+
return;
|
|
104
|
+
try {
|
|
105
|
+
// First attempt to set the metadata
|
|
106
|
+
await this._localCache.set(key, value);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.warn('Failed to store metadata in cache, attempting to clean up old entries:', error);
|
|
110
|
+
try {
|
|
111
|
+
// Get all keys that start with RAW_META/
|
|
112
|
+
const allKeys = await this._localCache.keys();
|
|
113
|
+
const metadataKeys = allKeys.filter(k => k.startsWith('RAW_META/') && k !== key);
|
|
114
|
+
// Remove all other metadata entries
|
|
115
|
+
for (const metaKey of metadataKeys) {
|
|
116
|
+
await this._localCache.remove(metaKey);
|
|
117
|
+
}
|
|
118
|
+
console.info(`Cleaned up ${metadataKeys.length} old metadata entries, trying again`);
|
|
119
|
+
// Try again after cleanup
|
|
120
|
+
await this._localCache.set(key, value);
|
|
121
|
+
}
|
|
122
|
+
catch (cleanupError) {
|
|
123
|
+
// If it still fails after cleanup, log the error but continue
|
|
124
|
+
console.error('Failed to store metadata even after cleanup:', cleanupError);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
97
128
|
setMetadata(metadata) {
|
|
98
129
|
this._metadata = metadata;
|
|
99
130
|
this._registry = new codecs_1.PortableRegistry(metadata.latest, this.options.hasher);
|
|
@@ -77,17 +77,25 @@ class StorageQueryExecutor extends Executor_js_1.Executor {
|
|
|
77
77
|
return queryFn;
|
|
78
78
|
}
|
|
79
79
|
exposeStorageMapMethods(entry) {
|
|
80
|
-
const rawKeys = async (pagination) => {
|
|
80
|
+
const rawKeys = async (partialInput, pagination) => {
|
|
81
81
|
const pageSize = pagination?.pageSize || DEFAULT_KEYS_PAGE_SIZE;
|
|
82
82
|
const startKey = pagination?.startKey || entry.prefixKey;
|
|
83
|
-
return await this.client.rpc.state_getKeysPaged(entry.
|
|
83
|
+
return await this.client.rpc.state_getKeysPaged(entry.encodeKey(partialInput, true), pageSize, startKey, this.atBlockHash);
|
|
84
84
|
};
|
|
85
|
-
const
|
|
86
|
-
const
|
|
85
|
+
const extractArgs = (args) => {
|
|
86
|
+
const inArgs = args.slice();
|
|
87
|
+
const lastArg = args.at(-1);
|
|
88
|
+
const pagination = (0, utils_1.isObject)(lastArg) && ('pageSize' in lastArg || 'startKey' in lastArg) ? inArgs.pop() : undefined;
|
|
89
|
+
return [inArgs, pagination];
|
|
90
|
+
};
|
|
91
|
+
const pagedKeys = async (...args) => {
|
|
92
|
+
const [inArgs, pagination] = extractArgs(args);
|
|
93
|
+
const storageKeys = await rawKeys(inArgs, { pageSize: DEFAULT_KEYS_PAGE_SIZE, ...pagination });
|
|
87
94
|
return storageKeys.map((key) => entry.decodeKey(key));
|
|
88
95
|
};
|
|
89
|
-
const pagedEntries = async (
|
|
90
|
-
const
|
|
96
|
+
const pagedEntries = async (...args) => {
|
|
97
|
+
const [inArgs, pagination] = extractArgs(args);
|
|
98
|
+
const storageKeys = await rawKeys(inArgs, { pageSize: DEFAULT_ENTRIES_PAGE_SIZE, ...pagination });
|
|
91
99
|
const storageMap = await this.queryStorage(storageKeys, this.atBlockHash);
|
|
92
100
|
return storageKeys.map((key) => [entry.decodeKey(key), entry.decodeValue(storageMap[key])]);
|
|
93
101
|
};
|
|
@@ -18,8 +18,12 @@ class StorageQueryExecutorV2 extends StorageQueryExecutor_js_1.StorageQueryExecu
|
|
|
18
18
|
// so for now we're trying to pull all entries from storage
|
|
19
19
|
// this might take a while for large storage
|
|
20
20
|
// TODO improve this, fallback to use `archive`-prefixed if available?
|
|
21
|
-
const entries = async () => {
|
|
22
|
-
const
|
|
21
|
+
const entries = async (...args) => {
|
|
22
|
+
const withArgs = !!args && args.length > 0;
|
|
23
|
+
const key = withArgs ? entry.encodeKey(args, true) : entry.prefixKey;
|
|
24
|
+
const results = await this.chainHead.storage([
|
|
25
|
+
{ type: 'descendantsValues', key },
|
|
26
|
+
]);
|
|
23
27
|
return results.map(({ key, value }) => [
|
|
24
28
|
entry.decodeKey(key),
|
|
25
29
|
entry.decodeValue(value),
|
|
@@ -54,17 +54,18 @@ class QueryableStorage {
|
|
|
54
54
|
* Encode plain key input to raw/bytes storage key
|
|
55
55
|
*
|
|
56
56
|
* @param keyInput
|
|
57
|
+
* @param allowPartialKeys - allow partial keys, default is false
|
|
57
58
|
*/
|
|
58
|
-
encodeKey(keyInput) {
|
|
59
|
+
encodeKey(keyInput, allowPartialKeys = false) {
|
|
59
60
|
const { storageType } = this.storageEntry;
|
|
60
61
|
if (storageType.type === 'Plain') {
|
|
61
62
|
return this.prefixKey;
|
|
62
63
|
}
|
|
63
64
|
else if (storageType.type === 'Map') {
|
|
64
65
|
const { hashers, keyTypeIds } = this.#getStorageMapInfo(storageType);
|
|
65
|
-
const extractedInputs = this.#extractRequiredKeyInputs(keyInput, hashers.length);
|
|
66
|
-
const keyParts =
|
|
67
|
-
const
|
|
66
|
+
const extractedInputs = this.#extractRequiredKeyInputs(keyInput, hashers.length, allowPartialKeys);
|
|
67
|
+
const keyParts = extractedInputs.map((input, index) => {
|
|
68
|
+
const keyId = keyTypeIds[index];
|
|
68
69
|
const hasher = utils_1.HASHERS[hashers[index]];
|
|
69
70
|
const $keyCodec = this.registry.findCodec(keyId);
|
|
70
71
|
return hasher($keyCodec.tryEncode(input));
|
|
@@ -125,7 +126,7 @@ class QueryableStorage {
|
|
|
125
126
|
return this.registry.findCodec(valueTypeId).tryDecode(codecs_1.$StorageData.tryEncode(raw));
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
|
-
#extractRequiredKeyInputs(keyInput, numberOfValue) {
|
|
129
|
+
#extractRequiredKeyInputs(keyInput, numberOfValue, allowPartialKeys = false) {
|
|
129
130
|
if (numberOfValue === 0) {
|
|
130
131
|
return [];
|
|
131
132
|
}
|
|
@@ -134,16 +135,25 @@ class QueryableStorage {
|
|
|
134
135
|
throw new Error(`Invalid key inputs, required ${numberOfValue} input(s)`);
|
|
135
136
|
}
|
|
136
137
|
if (numberOfValue === 1) {
|
|
137
|
-
return [keyInput];
|
|
138
|
+
return allowPartialKeys && Array.isArray(keyInput) ? keyInput : [keyInput];
|
|
138
139
|
}
|
|
139
140
|
else {
|
|
140
141
|
if (!Array.isArray(keyInput)) {
|
|
141
142
|
throw new Error(`Input should be an array with ${numberOfValue} value(s)`);
|
|
142
143
|
}
|
|
143
|
-
if (
|
|
144
|
-
|
|
144
|
+
if (allowPartialKeys) {
|
|
145
|
+
if (keyInput.length >= numberOfValue) {
|
|
146
|
+
throw new Error(`Invalid key inputs, partial key inputs should be less than the required key inputs, (max: ${numberOfValue - 1})`);
|
|
147
|
+
}
|
|
148
|
+
// TODO we need to make sure only filter out values in the last positions
|
|
149
|
+
return keyInput.slice(0, numberOfValue).filter((one) => one !== undefined && one !== null);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
if (keyInput.length !== numberOfValue) {
|
|
153
|
+
throw new Error(`Mismatch key inputs length, required an array of ${numberOfValue} value(s)`);
|
|
154
|
+
}
|
|
155
|
+
return keyInput.slice(0, numberOfValue);
|
|
145
156
|
}
|
|
146
|
-
return keyInput.slice(0, numberOfValue);
|
|
147
157
|
}
|
|
148
158
|
}
|
|
149
159
|
}
|
|
@@ -24,6 +24,10 @@ export declare abstract class BaseSubstrateClient<Rv extends RpcVersion, ChainAp
|
|
|
24
24
|
protected normalizeOptions(options: ApiOptions | JsonRpcProvider): ApiOptions;
|
|
25
25
|
protected initializeLocalCache(): Promise<void>;
|
|
26
26
|
protected setupMetadata(preloadMetadata: Metadata | undefined): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Safely set metadata to cache with fallback cleanup if storage limit is exceeded
|
|
29
|
+
*/
|
|
30
|
+
protected safeSetMetadataToCache(key: string, value: string): Promise<void>;
|
|
27
31
|
protected setMetadata(metadata: Metadata): void;
|
|
28
32
|
protected getMetadataKey(runtime?: SubstrateRuntimeVersion): MetadataKey;
|
|
29
33
|
get currentMetadataKey(): string;
|
|
@@ -83,13 +83,44 @@ export class BaseSubstrateClient extends JsonRpcClient {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
if (shouldUpdateCache && this._localCache) {
|
|
86
|
-
|
|
86
|
+
const encodedMetadata = u8aToHex($Metadata.tryEncode(metadata));
|
|
87
|
+
await this.safeSetMetadataToCache(metadataKey, encodedMetadata);
|
|
87
88
|
}
|
|
88
89
|
if (!metadata) {
|
|
89
90
|
throw new Error('Cannot load metadata');
|
|
90
91
|
}
|
|
91
92
|
this.setMetadata(metadata);
|
|
92
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Safely set metadata to cache with fallback cleanup if storage limit is exceeded
|
|
96
|
+
*/
|
|
97
|
+
async safeSetMetadataToCache(key, value) {
|
|
98
|
+
if (!this._localCache)
|
|
99
|
+
return;
|
|
100
|
+
try {
|
|
101
|
+
// First attempt to set the metadata
|
|
102
|
+
await this._localCache.set(key, value);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.warn('Failed to store metadata in cache, attempting to clean up old entries:', error);
|
|
106
|
+
try {
|
|
107
|
+
// Get all keys that start with RAW_META/
|
|
108
|
+
const allKeys = await this._localCache.keys();
|
|
109
|
+
const metadataKeys = allKeys.filter(k => k.startsWith('RAW_META/') && k !== key);
|
|
110
|
+
// Remove all other metadata entries
|
|
111
|
+
for (const metaKey of metadataKeys) {
|
|
112
|
+
await this._localCache.remove(metaKey);
|
|
113
|
+
}
|
|
114
|
+
console.info(`Cleaned up ${metadataKeys.length} old metadata entries, trying again`);
|
|
115
|
+
// Try again after cleanup
|
|
116
|
+
await this._localCache.set(key, value);
|
|
117
|
+
}
|
|
118
|
+
catch (cleanupError) {
|
|
119
|
+
// If it still fails after cleanup, log the error but continue
|
|
120
|
+
console.error('Failed to store metadata even after cleanup:', cleanupError);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
93
124
|
setMetadata(metadata) {
|
|
94
125
|
this._metadata = metadata;
|
|
95
126
|
this._registry = new PortableRegistry(metadata.latest, this.options.hasher);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assert, isFunction } from '@dedot/utils';
|
|
1
|
+
import { assert, isFunction, isObject } from '@dedot/utils';
|
|
2
2
|
import { QueryableStorage } from '../storage/QueryableStorage.js';
|
|
3
3
|
import { Executor } from './Executor.js';
|
|
4
4
|
const DEFAULT_KEYS_PAGE_SIZE = 1000;
|
|
@@ -74,17 +74,25 @@ export class StorageQueryExecutor extends Executor {
|
|
|
74
74
|
return queryFn;
|
|
75
75
|
}
|
|
76
76
|
exposeStorageMapMethods(entry) {
|
|
77
|
-
const rawKeys = async (pagination) => {
|
|
77
|
+
const rawKeys = async (partialInput, pagination) => {
|
|
78
78
|
const pageSize = pagination?.pageSize || DEFAULT_KEYS_PAGE_SIZE;
|
|
79
79
|
const startKey = pagination?.startKey || entry.prefixKey;
|
|
80
|
-
return await this.client.rpc.state_getKeysPaged(entry.
|
|
80
|
+
return await this.client.rpc.state_getKeysPaged(entry.encodeKey(partialInput, true), pageSize, startKey, this.atBlockHash);
|
|
81
81
|
};
|
|
82
|
-
const
|
|
83
|
-
const
|
|
82
|
+
const extractArgs = (args) => {
|
|
83
|
+
const inArgs = args.slice();
|
|
84
|
+
const lastArg = args.at(-1);
|
|
85
|
+
const pagination = isObject(lastArg) && ('pageSize' in lastArg || 'startKey' in lastArg) ? inArgs.pop() : undefined;
|
|
86
|
+
return [inArgs, pagination];
|
|
87
|
+
};
|
|
88
|
+
const pagedKeys = async (...args) => {
|
|
89
|
+
const [inArgs, pagination] = extractArgs(args);
|
|
90
|
+
const storageKeys = await rawKeys(inArgs, { pageSize: DEFAULT_KEYS_PAGE_SIZE, ...pagination });
|
|
84
91
|
return storageKeys.map((key) => entry.decodeKey(key));
|
|
85
92
|
};
|
|
86
|
-
const pagedEntries = async (
|
|
87
|
-
const
|
|
93
|
+
const pagedEntries = async (...args) => {
|
|
94
|
+
const [inArgs, pagination] = extractArgs(args);
|
|
95
|
+
const storageKeys = await rawKeys(inArgs, { pageSize: DEFAULT_ENTRIES_PAGE_SIZE, ...pagination });
|
|
88
96
|
const storageMap = await this.queryStorage(storageKeys, this.atBlockHash);
|
|
89
97
|
return storageKeys.map((key) => [entry.decodeKey(key), entry.decodeValue(storageMap[key])]);
|
|
90
98
|
};
|
|
@@ -15,8 +15,12 @@ export class StorageQueryExecutorV2 extends StorageQueryExecutor {
|
|
|
15
15
|
// so for now we're trying to pull all entries from storage
|
|
16
16
|
// this might take a while for large storage
|
|
17
17
|
// TODO improve this, fallback to use `archive`-prefixed if available?
|
|
18
|
-
const entries = async () => {
|
|
19
|
-
const
|
|
18
|
+
const entries = async (...args) => {
|
|
19
|
+
const withArgs = !!args && args.length > 0;
|
|
20
|
+
const key = withArgs ? entry.encodeKey(args, true) : entry.prefixKey;
|
|
21
|
+
const results = await this.chainHead.storage([
|
|
22
|
+
{ type: 'descendantsValues', key },
|
|
23
|
+
]);
|
|
20
24
|
return results.map(({ key, value }) => [
|
|
21
25
|
entry.decodeKey(key),
|
|
22
26
|
entry.decodeValue(value),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1-next.4880b708.2+4880b70",
|
|
4
4
|
"description": "A delightful JavaScript/TypeScript client for Polkadot & Substrate",
|
|
5
5
|
"author": "Thang X. Vu <thang@coongcrafts.io>",
|
|
6
6
|
"homepage": "https://github.com/dedotdev/dedot/tree/main/packages/api",
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"type": "module",
|
|
14
14
|
"sideEffects": false,
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@dedot/codecs": "0.
|
|
17
|
-
"@dedot/providers": "0.
|
|
18
|
-
"@dedot/runtime-specs": "0.
|
|
19
|
-
"@dedot/shape": "0.
|
|
20
|
-
"@dedot/storage": "0.
|
|
21
|
-
"@dedot/types": "0.
|
|
22
|
-
"@dedot/utils": "0.
|
|
16
|
+
"@dedot/codecs": "0.8.1-next.4880b708.2+4880b70",
|
|
17
|
+
"@dedot/providers": "0.8.1-next.4880b708.2+4880b70",
|
|
18
|
+
"@dedot/runtime-specs": "0.8.1-next.4880b708.2+4880b70",
|
|
19
|
+
"@dedot/shape": "0.8.1-next.4880b708.2+4880b70",
|
|
20
|
+
"@dedot/storage": "0.8.1-next.4880b708.2+4880b70",
|
|
21
|
+
"@dedot/types": "0.8.1-next.4880b708.2+4880b70",
|
|
22
|
+
"@dedot/utils": "0.8.1-next.4880b708.2+4880b70"
|
|
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": "
|
|
51
|
+
"gitHead": "4880b708ff98e75c257bf82ec80b3d63b0fb1458",
|
|
52
52
|
"module": "./index.js",
|
|
53
53
|
"types": "./index.d.ts"
|
|
54
54
|
}
|
|
@@ -17,8 +17,9 @@ export declare class QueryableStorage {
|
|
|
17
17
|
* Encode plain key input to raw/bytes storage key
|
|
18
18
|
*
|
|
19
19
|
* @param keyInput
|
|
20
|
+
* @param allowPartialKeys - allow partial keys, default is false
|
|
20
21
|
*/
|
|
21
|
-
encodeKey(keyInput?: any): StorageKey;
|
|
22
|
+
encodeKey(keyInput?: any, allowPartialKeys?: boolean): StorageKey;
|
|
22
23
|
/**
|
|
23
24
|
* Decode storage key to plain key input
|
|
24
25
|
* Only storage keys that hashed by `twox64Concat`, `blake2_128Concat`, or `identity` can be decoded
|
|
@@ -51,17 +51,18 @@ export class QueryableStorage {
|
|
|
51
51
|
* Encode plain key input to raw/bytes storage key
|
|
52
52
|
*
|
|
53
53
|
* @param keyInput
|
|
54
|
+
* @param allowPartialKeys - allow partial keys, default is false
|
|
54
55
|
*/
|
|
55
|
-
encodeKey(keyInput) {
|
|
56
|
+
encodeKey(keyInput, allowPartialKeys = false) {
|
|
56
57
|
const { storageType } = this.storageEntry;
|
|
57
58
|
if (storageType.type === 'Plain') {
|
|
58
59
|
return this.prefixKey;
|
|
59
60
|
}
|
|
60
61
|
else if (storageType.type === 'Map') {
|
|
61
62
|
const { hashers, keyTypeIds } = this.#getStorageMapInfo(storageType);
|
|
62
|
-
const extractedInputs = this.#extractRequiredKeyInputs(keyInput, hashers.length);
|
|
63
|
-
const keyParts =
|
|
64
|
-
const
|
|
63
|
+
const extractedInputs = this.#extractRequiredKeyInputs(keyInput, hashers.length, allowPartialKeys);
|
|
64
|
+
const keyParts = extractedInputs.map((input, index) => {
|
|
65
|
+
const keyId = keyTypeIds[index];
|
|
65
66
|
const hasher = HASHERS[hashers[index]];
|
|
66
67
|
const $keyCodec = this.registry.findCodec(keyId);
|
|
67
68
|
return hasher($keyCodec.tryEncode(input));
|
|
@@ -122,7 +123,7 @@ export class QueryableStorage {
|
|
|
122
123
|
return this.registry.findCodec(valueTypeId).tryDecode($StorageData.tryEncode(raw));
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
|
-
#extractRequiredKeyInputs(keyInput, numberOfValue) {
|
|
126
|
+
#extractRequiredKeyInputs(keyInput, numberOfValue, allowPartialKeys = false) {
|
|
126
127
|
if (numberOfValue === 0) {
|
|
127
128
|
return [];
|
|
128
129
|
}
|
|
@@ -131,16 +132,25 @@ export class QueryableStorage {
|
|
|
131
132
|
throw new Error(`Invalid key inputs, required ${numberOfValue} input(s)`);
|
|
132
133
|
}
|
|
133
134
|
if (numberOfValue === 1) {
|
|
134
|
-
return [keyInput];
|
|
135
|
+
return allowPartialKeys && Array.isArray(keyInput) ? keyInput : [keyInput];
|
|
135
136
|
}
|
|
136
137
|
else {
|
|
137
138
|
if (!Array.isArray(keyInput)) {
|
|
138
139
|
throw new Error(`Input should be an array with ${numberOfValue} value(s)`);
|
|
139
140
|
}
|
|
140
|
-
if (
|
|
141
|
-
|
|
141
|
+
if (allowPartialKeys) {
|
|
142
|
+
if (keyInput.length >= numberOfValue) {
|
|
143
|
+
throw new Error(`Invalid key inputs, partial key inputs should be less than the required key inputs, (max: ${numberOfValue - 1})`);
|
|
144
|
+
}
|
|
145
|
+
// TODO we need to make sure only filter out values in the last positions
|
|
146
|
+
return keyInput.slice(0, numberOfValue).filter((one) => one !== undefined && one !== null);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
if (keyInput.length !== numberOfValue) {
|
|
150
|
+
throw new Error(`Mismatch key inputs length, required an array of ${numberOfValue} value(s)`);
|
|
151
|
+
}
|
|
152
|
+
return keyInput.slice(0, numberOfValue);
|
|
142
153
|
}
|
|
143
|
-
return keyInput.slice(0, numberOfValue);
|
|
144
154
|
}
|
|
145
155
|
}
|
|
146
156
|
}
|