@talismn/scale 0.0.2 → 0.1.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 (52) hide show
  1. package/dist/declarations/src/index.d.ts +2 -3
  2. package/dist/declarations/src/papito.d.ts +6 -0
  3. package/dist/declarations/src/util/compactMetadata.d.ts +24 -0
  4. package/dist/declarations/src/util/decodeMetadata.d.ts +13 -0
  5. package/dist/declarations/src/util/decodeScale.d.ts +4 -0
  6. package/dist/declarations/src/util/encodeMetadata.d.ts +8 -0
  7. package/dist/declarations/src/util/encodeStateKey.d.ts +4 -0
  8. package/dist/declarations/src/util/getMetadataVersion.d.ts +6 -0
  9. package/dist/declarations/src/util/index.d.ts +7 -0
  10. package/dist/declarations/src/util/serdePapi.d.ts +30 -0
  11. package/dist/talismn-scale.cjs.dev.js +338 -1691
  12. package/dist/talismn-scale.cjs.prod.js +338 -1691
  13. package/dist/talismn-scale.esm.js +305 -1618
  14. package/package.json +16 -20
  15. package/CHANGELOG.md +0 -15
  16. package/dist/declarations/src/capi/crypto/base58.d.ts +0 -18
  17. package/dist/declarations/src/capi/crypto/hashers.d.ts +0 -67
  18. package/dist/declarations/src/capi/crypto/index.d.ts +0 -3
  19. package/dist/declarations/src/capi/crypto/ss58.d.ts +0 -16
  20. package/dist/declarations/src/capi/crypto/util/index.d.ts +0 -4
  21. package/dist/declarations/src/capi/crypto/util/nosimd.d.ts +0 -19
  22. package/dist/declarations/src/capi/crypto/util/simd.d.ts +0 -1
  23. package/dist/declarations/src/capi/frame_metadata/Extrinsic.d.ts +0 -50
  24. package/dist/declarations/src/capi/frame_metadata/FrameMetadata.d.ts +0 -61
  25. package/dist/declarations/src/capi/frame_metadata/decodeMetadata.d.ts +0 -312
  26. package/dist/declarations/src/capi/frame_metadata/index.d.ts +0 -4
  27. package/dist/declarations/src/capi/frame_metadata/key_codecs.d.ts +0 -27
  28. package/dist/declarations/src/capi/frame_metadata/raw/v14.d.ts +0 -312
  29. package/dist/declarations/src/capi/index.d.ts +0 -4
  30. package/dist/declarations/src/capi/scale_info/index.d.ts +0 -4
  31. package/dist/declarations/src/capi/scale_info/overrides/ChainError.d.ts +0 -26
  32. package/dist/declarations/src/capi/scale_info/overrides/Era.d.ts +0 -33
  33. package/dist/declarations/src/capi/scale_info/overrides/index.d.ts +0 -1
  34. package/dist/declarations/src/capi/scale_info/overrides/overrides.d.ts +0 -23
  35. package/dist/declarations/src/capi/scale_info/raw/Ty.d.ts +0 -313
  36. package/dist/declarations/src/capi/scale_info/transformTys.d.ts +0 -34
  37. package/dist/declarations/src/capi/util/index.d.ts +0 -3
  38. package/dist/declarations/src/capi/util/key.d.ts +0 -22
  39. package/dist/declarations/src/capi/util/normalize.d.ts +0 -25
  40. package/dist/declarations/src/capi/util/state.d.ts +0 -25
  41. package/dist/declarations/src/metadata/index.d.ts +0 -2
  42. package/dist/declarations/src/metadata/util.d.ts +0 -10
  43. package/dist/declarations/src/storage/getShape.d.ts +0 -15
  44. package/dist/declarations/src/storage/getTypeName.d.ts +0 -25
  45. package/dist/declarations/src/storage/index.d.ts +0 -11
  46. package/dist/declarations/src/suppressPortableRegistryConsoleWarnings.d.ts +0 -1
  47. package/dist/nosimd-18c022ec.cjs.dev.js +0 -46
  48. package/dist/nosimd-8c31fb2d.esm.js +0 -43
  49. package/dist/nosimd-b32b4901.cjs.prod.js +0 -46
  50. package/dist/simd-133b8f48.cjs.prod.js +0 -14
  51. package/dist/simd-2ddb8d7c.cjs.dev.js +0 -14
  52. package/dist/simd-b794dbff.esm.js +0 -1
@@ -1,1450 +1,139 @@
1
- import { Deferred } from '@talismn/util';
2
- import { simd } from 'wasm-feature-detect';
3
- import * as $ from '@talismn/subshape-fork';
4
- import { EncodeBuffer } from '@talismn/subshape-fork';
1
+ export { getDynamicBuilder, getLookupFn } from '@polkadot-api/metadata-builders';
2
+ import { toHex } from '@polkadot-api/utils';
3
+ export { fromHex, toHex } from '@polkadot-api/utils';
4
+ import { metadata, Binary } from '@polkadot-api/substrate-bindings';
5
+ export { metadata, v14, v15 } from '@polkadot-api/substrate-bindings';
5
6
  import anylogger from 'anylogger';
7
+ import { Struct, u8, u32 } from 'scale-ts';
6
8
 
7
- const ignoreModuleMessages = {
8
- "PORTABLEREGISTRY:": ["Unable to determine runtime Event type, cannot inspect frame_system::EventRecord", "Unable to determine runtime Call type, cannot inspect sp_runtime::generic::unchecked_extrinsic::UncheckedExtrinsic"]
9
- };
10
- function suppressPortableRegistryConsoleWarnings() {
11
- /* eslint-disable-next-line no-console */
12
- const originalWarn = console.warn;
13
-
14
- /* eslint-disable-next-line no-console */
15
- console.warn = (...data) => {
16
- const [, dataModule, dataMessage] = data;
17
- const ignoreMessages = typeof dataModule === "string" && ignoreModuleMessages[dataModule];
18
- if (Array.isArray(ignoreMessages) && ignoreMessages.includes(dataMessage)) return;
19
- if (data[0] === "Unable to map Bytes to a lookup index") return;
20
- if (data[0] === "Unable to map [u8; 32] to a lookup index") return;
21
- if (data[0] === "Unable to map u16 to a lookup index") return;
22
- if (data[0] === "Unable to map u32 to a lookup index") return;
23
- if (data[0] === "Unable to map u64 to a lookup index") return;
24
- if (data[0] === "Unable to map u128 to a lookup index") return;
25
- originalWarn(...data);
26
- };
27
- }
28
-
29
- //
30
- // The simd variants of these hash fns are faster, but some devices don't support them.
31
- //
32
- // This file re-exports the faster fns from `./simd` for devices which support them,
33
- // and falls back to `./nosimd` re-exports for devices which do not.
34
- //
35
- /**
36
- * Show a useful error message when someone attempts to use one of the classes
37
- * from this lib without waiting for them to be initialized.
38
- */
39
- class UninitializedHasher {
40
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
41
- constructor(...args) {
42
- throw new Error(`This class cannot be used before @talismn/scale has initialized it. Please await 'watCryptoWaitReady' before attempting to construct this class.`);
43
- }
44
-
45
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
46
- update(input) {
47
- throw new Error(`This class cannot be used before @talismn/scale has initialized it. Please await 'watCryptoWaitReady' before attempting to construct this class.`);
48
- }
49
- digest() {
50
- throw new Error(`This class cannot be used before @talismn/scale has initialized it. Please await 'watCryptoWaitReady' before attempting to construct this class.`);
51
- }
52
- digestInto(digest) {
53
- digest.set(this.digest());
54
- }
55
- dispose() {
56
- throw new Error(`This class cannot be used before @talismn/scale has initialized it. Please await 'watCryptoWaitReady' before attempting to construct this class.`);
57
- }
58
- }
59
-
60
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
- let Blake2b = UninitializedHasher;
62
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
- let Xxhash = UninitializedHasher;
64
- let readyPromise = null;
65
- const watCryptoWaitReady = async () => {
66
- // if this is the second/third/etc time we've called watCryptoWaitReady,
67
- // then get a reference to the existing promise and wait for it to resolve/reject
68
- if (readyPromise !== null) return await readyPromise;
69
-
70
- // if this is the first time we've called watCryptoWaitReady,
71
- // then create and return a new promise
72
- const deferred = Deferred();
73
- readyPromise = deferred.promise
74
-
75
- // spawn a task to initialize the fns and resolve the readyPromise
76
- ;
77
- (async () => {
78
- try {
79
- // initialize simd or nosimd, based on wasm feature detection
80
- if (await simd()) {
81
- // system supports wasm simd
82
- const imported = await import('./simd-b794dbff.esm.js');
83
- Blake2b = imported.Blake2b;
84
- Xxhash = imported.Xxhash;
85
- } else {
86
- // system does not support wasm simd
87
- const imported = await import('./nosimd-8c31fb2d.esm.js');
88
- Blake2b = imported.Blake2b;
89
- Xxhash = imported.Xxhash;
90
- }
91
-
92
- // feature detection and loading complete
93
- deferred.resolve();
94
- } catch (error) {
95
- // feature detection and loading failed
96
- deferred.reject(error);
97
- }
98
- })();
99
-
100
- // wait for the promise to resolve/reject
101
- return await readyPromise;
102
- };
103
-
104
- // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
105
- // This module is browser compatible.
106
-
107
- /**
108
- * {@linkcode encode} and {@linkcode decode} for
109
- * [base58](https://en.wikipedia.org/wiki/Binary-to-text_encoding#Base58) encoding.
110
- *
111
- * This module is browser compatible.
112
- *
113
- * @module
114
- */
115
-
116
- // deno-fmt-ignore
117
- const mapBase58 = {
118
- "1": 0,
119
- "2": 1,
120
- "3": 2,
121
- "4": 3,
122
- "5": 4,
123
- "6": 5,
124
- "7": 6,
125
- "8": 7,
126
- "9": 8,
127
- "A": 9,
128
- "B": 10,
129
- "C": 11,
130
- "D": 12,
131
- "E": 13,
132
- "F": 14,
133
- "G": 15,
134
- "H": 16,
135
- "J": 17,
136
- "K": 18,
137
- "L": 19,
138
- "M": 20,
139
- "N": 21,
140
- "P": 22,
141
- "Q": 23,
142
- "R": 24,
143
- "S": 25,
144
- "T": 26,
145
- "U": 27,
146
- "V": 28,
147
- "W": 29,
148
- "X": 30,
149
- "Y": 31,
150
- "Z": 32,
151
- "a": 33,
152
- "b": 34,
153
- "c": 35,
154
- "d": 36,
155
- "e": 37,
156
- "f": 38,
157
- "g": 39,
158
- "h": 40,
159
- "i": 41,
160
- "j": 42,
161
- "k": 43,
162
- "m": 44,
163
- "n": 45,
164
- "o": 46,
165
- "p": 47,
166
- "q": 48,
167
- "r": 49,
168
- "s": 50,
169
- "t": 51,
170
- "u": 52,
171
- "v": 53,
172
- "w": 54,
173
- "x": 55,
174
- "y": 56,
175
- "z": 57
176
- };
177
- const base58alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".split("");
178
-
179
- /**
180
- * Encodes a given Uint8Array, ArrayBuffer or string into draft-mspotny-base58-03 RFC base58 representation:
181
- * https://tools.ietf.org/id/draft-msporny-base58-01.html#rfc.section.1
182
- *
183
- * @param data
184
- *
185
- * @returns Encoded value
186
- */
187
- function encode$1(data) {
188
- const uint8tData = typeof data === "string" ? new TextEncoder().encode(data) : data instanceof Uint8Array ? data : new Uint8Array(data);
189
- let length = 0;
190
- let zeroes = 0;
191
-
192
- // Counting leading zeroes
193
- let index = 0;
194
- while (uint8tData[index] === 0) {
195
- zeroes++;
196
- index++;
197
- }
198
- const notZeroUint8Data = uint8tData.slice(index);
199
- const size = Math.round(uint8tData.length * 138 / 100 + 1);
200
- const b58Encoding = [];
201
- notZeroUint8Data.forEach(byte => {
202
- let i = 0;
203
- let carry = byte;
204
- for (let reverse_iterator = size - 1; (carry > 0 || i < length) && reverse_iterator !== -1; reverse_iterator--, i++) {
205
- carry += (b58Encoding[reverse_iterator] || 0) * 256;
206
- b58Encoding[reverse_iterator] = Math.round(carry % 58);
207
- carry = Math.floor(carry / 58);
208
- }
209
- length = i;
210
- });
211
- const strResult = Array.from({
212
- length: b58Encoding.length + zeroes
213
- });
214
- if (zeroes > 0) {
215
- strResult.fill("1", 0, zeroes);
216
- }
217
- b58Encoding.forEach(byteValue => strResult.push(base58alphabet[byteValue]));
218
- return strResult.join("");
219
- }
220
-
221
- /**
222
- * Decodes a given b58 string according to draft-mspotny-base58-03 RFC base58 representation:
223
- * https://tools.ietf.org/id/draft-msporny-base58-01.html#rfc.section.1
224
- *
225
- * @param b58
226
- *
227
- * @returns Decoded value
228
- */
229
- function decode$1(b58) {
230
- const splitInput = b58.trim().split("");
231
- let length = 0;
232
- let ones = 0;
233
-
234
- // Counting leading ones
235
- let index = 0;
236
- while (splitInput[index] === "1") {
237
- ones++;
238
- index++;
239
- }
240
- const notZeroData = splitInput.slice(index);
241
- const size = Math.round(b58.length * 733 / 1000 + 1);
242
- const output = [];
243
- notZeroData.forEach((char, idx) => {
244
- let carry = mapBase58[char];
245
- let i = 0;
246
- if (carry === undefined) {
247
- throw new Error(`Invalid base58 char at index ${idx} with value ${char}`);
248
- }
249
- for (let reverse_iterator = size - 1; (carry > 0 || i < length) && reverse_iterator !== -1; reverse_iterator--, i++) {
250
- carry += 58 * (output[reverse_iterator] || 0);
251
- output[reverse_iterator] = Math.round(carry % 256);
252
- carry = Math.floor(carry / 256);
253
- }
254
- length = i;
255
- });
256
- const validOutput = output.filter(item => item !== undefined);
257
- if (ones > 0) {
258
- const onesResult = Array.from({
259
- length: ones
260
- }).fill(0, 0, ones);
261
- return new Uint8Array([...onesResult, ...validOutput]);
262
- }
263
- return new Uint8Array(validOutput);
264
- }
265
-
266
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
267
- function encode(prefix, payload, checksumLength) {
268
- return encode$1(encodeRaw(prefix, payload, checksumLength));
269
- }
270
- function encodeRaw(prefix, payload, checksumLength) {
271
- checksumLength ??= DEFAULT_PAYLOAD_CHECKSUM_LENGTHS[payload.length];
272
- if (!checksumLength) throw new InvalidPayloadLengthError();
273
- const prefixBytes = prefix < 64 ? Uint8Array.of(prefix) : Uint8Array.of((prefix & 0b0000_0000_1111_1100) >> 2 | 0b0100_0000, prefix >> 8 | (prefix & 0b0000_0000_0000_0011) << 6);
274
- const hasher = new Blake2b();
275
- hasher.update(SS58PRE);
276
- hasher.update(prefixBytes);
277
- hasher.update(payload);
278
- const digest = hasher.digest();
279
- const checksum = digest.subarray(0, checksumLength);
280
- hasher.dispose();
281
- const address = new Uint8Array(prefixBytes.length + payload.length + checksumLength);
282
- address.set(prefixBytes, 0);
283
- address.set(payload, prefixBytes.length);
284
- address.set(checksum, prefixBytes.length + payload.length);
285
- return address;
286
- }
287
- class InvalidPayloadLengthError extends Error {
288
- name = "InvalidPayloadLengthError";
289
- }
290
- function decode(address) {
291
- return decodeRaw(decode$1(address));
292
- }
293
- function decodeRaw(address) {
294
- const checksumLength = VALID_ADDRESS_CHECKSUM_LENGTHS[address.length];
295
- if (!checksumLength) throw new InvalidAddressLengthError();
296
- const prefixLength = address[0] & 0b0100_0000 ? 2 : 1;
297
- const prefix = prefixLength === 1 ? address[0] : (address[0] & 0b0011_1111) << 2 | address[1] >> 6 | (address[1] & 0b0011_1111) << 8;
298
- const hasher = new Blake2b();
299
- hasher.update(SS58PRE);
300
- hasher.update(address.subarray(0, address.length - checksumLength));
301
- const digest = hasher.digest();
302
- const checksum = address.subarray(address.length - checksumLength);
303
- hasher.dispose();
304
- if (!isValidChecksum(digest, checksum, checksumLength)) {
305
- throw new InvalidAddressChecksumError();
306
- }
307
- const pubKey = address.subarray(prefixLength, address.length - checksumLength);
308
- return [prefix, pubKey];
309
- }
310
- class InvalidAddressLengthError extends Error {
311
- name = "InvalidAddressError";
312
- }
313
- class InvalidAddressChecksumError extends Error {
314
- name = "InvalidAddressChecksumError";
315
- }
316
-
317
- // SS58PRE string (0x53533538505245 hex) encoded as Uint8Array
318
- const SS58PRE = Uint8Array.of(83, 83, 53, 56, 80, 82, 69);
319
- const VALID_ADDRESS_CHECKSUM_LENGTHS = {
320
- 3: 1,
321
- 4: 1,
322
- 5: 2,
323
- 6: 1,
324
- 7: 2,
325
- 8: 3,
326
- 9: 4,
327
- 10: 1,
328
- 11: 2,
329
- 12: 3,
330
- 13: 4,
331
- 14: 5,
332
- 15: 6,
333
- 16: 7,
334
- 17: 8,
335
- 35: 2,
336
- 36: 2,
337
- 37: 2
338
- };
339
- const DEFAULT_PAYLOAD_CHECKSUM_LENGTHS = {
340
- 1: 1,
341
- 2: 1,
342
- 4: 1,
343
- 8: 1,
344
- 32: 2,
345
- 33: 2
346
- };
347
- function isValidChecksum(digest, checksum, checksumLength) {
348
- for (let i = 0; i < checksumLength; i++) {
349
- if (digest[i] !== checksum[i]) {
350
- return false;
351
- }
352
- }
353
- return true;
354
- }
355
-
356
- var ss58 = /*#__PURE__*/Object.freeze({
357
- __proto__: null,
358
- encode: encode,
359
- encodeRaw: encodeRaw,
360
- InvalidPayloadLengthError: InvalidPayloadLengthError,
361
- decode: decode,
362
- decodeRaw: decodeRaw,
363
- InvalidAddressLengthError: InvalidAddressLengthError,
364
- InvalidAddressChecksumError: InvalidAddressChecksumError
365
- });
366
-
367
- /**
368
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
369
- * Changes August 19th 2023 :
370
- * - updated to use subshape for scale decoding
371
- * - adapted from deno to typescript
372
- *
373
- Copyright 2023 Parity Technologies
374
-
375
- Licensed under the Apache License, Version 2.0 (the "License");
376
- you may not use this file except in compliance with the License.
377
- You may obtain a copy of the License at
378
-
379
- http://www.apache.org/licenses/LICENSE-2.0
380
-
381
- Unless required by applicable law or agreed to in writing, software
382
- distributed under the License is distributed on an "AS IS" BASIS,
383
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
384
- See the License for the specific language governing permissions and
385
- limitations under the License.
386
- */
387
- class Hasher {
388
- $hash($inner) {
389
- return $hash(this, $inner);
390
- }
391
- hash(data) {
392
- const output = new Uint8Array(this.digestLength + (this.concat ? data.length : 0));
393
- const hashing = this.create();
394
- hashing.update(data);
395
- hashing.digestInto(output);
396
- hashing.dispose?.();
397
- if (this.concat) {
398
- output.set(data, this.digestLength);
399
- }
400
- return output;
401
- }
402
- }
403
- function $hash(hasher, $inner) {
404
- return $.createShape({
405
- metadata: $.metadata("$hash", $hash, hasher, $inner),
406
- staticSize: hasher.digestLength + $inner.staticSize,
407
- subEncode(buffer, value) {
408
- const hashArray = buffer.array.subarray(buffer.index, buffer.index += hasher.digestLength);
409
- const cursor = hasher.concat ? buffer.createCursor($inner.staticSize) : new EncodeBuffer(buffer.stealAlloc($inner.staticSize));
410
- $inner.subEncode(cursor, value);
411
- buffer.waitForBuffer(cursor, () => {
412
- if (hasher.concat) cursor.close();else cursor._commitWritten();
413
- const hashing = hasher.create();
414
- updateHashing(hashing, cursor);
415
- hashing.digestInto(hashArray);
416
- hashing.dispose?.();
417
- });
418
- },
419
- subDecode(buffer) {
420
- if (!hasher.concat) throw new DecodeNonTransparentKeyError();
421
- buffer.index += hasher.digestLength;
422
- return $inner.subDecode(buffer);
423
- },
424
- subAssert(assert) {
425
- $inner.subAssert(assert);
426
- }
427
- });
428
- }
429
- class Blake2Hasher extends Hasher {
430
- constructor(size, concat) {
431
- super();
432
- this.concat = concat;
433
- this.digestLength = size / 8;
434
- }
435
- create() {
436
- return new Blake2b(this.digestLength);
437
- }
438
- }
439
- class IdentityHasher extends Hasher {
440
- digestLength = 0;
441
- concat = true;
442
- create() {
443
- return {
444
- update() {},
445
- digestInto() {}
446
- };
447
- }
448
- $hash($inner) {
449
- return $inner;
450
- }
451
- hash(data) {
452
- return data.slice();
453
- }
454
- }
455
- class TwoxHasher extends Hasher {
456
- constructor(size, concat) {
457
- super();
458
- this.concat = concat;
459
- this.digestLength = size / 8;
460
- this.rounds = size / 64;
461
- }
462
- create() {
463
- return new Xxhash(this.rounds);
464
- }
465
- }
466
- const blake2_64 = new Blake2Hasher(64, false);
467
- const blake2_128 = new Blake2Hasher(128, false);
468
- const blake2_128Concat = new Blake2Hasher(128, true);
469
- const blake2_256 = new Blake2Hasher(256, false);
470
- const blake2_512 = new Blake2Hasher(512, false);
471
- const identity = new IdentityHasher();
472
- const twox64 = new TwoxHasher(64, false);
473
- const twox128 = new TwoxHasher(128, false);
474
- const twox256 = new TwoxHasher(256, false);
475
- const twox64Concat = new TwoxHasher(64, true);
476
- function updateHashing(hashing, data) {
477
- for (const array of data.finishedArrays) {
478
- if (array instanceof EncodeBuffer) {
479
- updateHashing(hashing, array);
480
- } else {
481
- hashing.update(array);
482
- }
483
- }
484
- }
485
- class DecodeNonTransparentKeyError extends Error {
486
- name = "DecodeNonTransparentKeyError";
487
- }
488
-
489
- /**
490
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
491
- * Changes August 19th 2023 :
492
- * - updated to use subshape for scale decoding
493
- * - adapted from deno to typescript
494
- *
495
- Copyright 2023 Parity Technologies
496
-
497
- Licensed under the Apache License, Version 2.0 (the "License");
498
- you may not use this file except in compliance with the License.
499
- You may obtain a copy of the License at
500
-
501
- http://www.apache.org/licenses/LICENSE-2.0
502
-
503
- Unless required by applicable law or agreed to in writing, software
504
- distributed under the License is distributed on an "AS IS" BASIS,
505
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
506
- See the License for the specific language governing permissions and
507
- limitations under the License.
508
- */
509
- const $tyId = $.compact($.u32);
510
- const $field = $.object($.optionalField("name", $.str), $.field("ty", $tyId), $.optionalField("typeName", $.str), $.field("docs", $.array($.str)));
511
- const $primitiveKind = $.literalUnion(["bool", "char", "str", "u8", "u16", "u32", "u64", "u128", "u256", "i8", "i16", "i32", "i64", "i128", "i256"]);
512
- const $tyDef = $.taggedUnion("type", [$.variant("Struct", $.field("fields", $.array($field))), $.variant("Union", $.field("members", $.array($.object($.field("name", $.str), $.field("fields", $.array($field)), $.field("index", $.u8), $.field("docs", $.array($.str)))))), $.variant("Sequence", $.field("typeParam", $tyId)), $.variant("SizedArray", $.field("len", $.u32), $.field("typeParam", $tyId)), $.variant("Tuple", $.field("fields", $.array($tyId))), $.variant("Primitive", $.field("kind", $primitiveKind)), $.variant("Compact", $.field("typeParam", $tyId)), $.variant("BitSequence", $.field("bitOrderType", $tyId), $.field("bitStoreType", $tyId))]);
513
- const $ty = $.object($.field("id", $.compact($.u32)), $.field("path", $.array($.str)), $.field("params", $.array($.object($.field("name", $.str), $.optionalField("ty", $tyId)))), $tyDef, $.field("docs", $.array($.str)));
514
-
515
- /**
516
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
517
- * Changes August 19th 2023 :
518
- * - updated to use subshape for scale decoding
519
- * - adapted from deno to typescript
520
- *
521
- Copyright 2023 Parity Technologies
522
-
523
- Licensed under the Apache License, Version 2.0 (the "License");
524
- you may not use this file except in compliance with the License.
525
- You may obtain a copy of the License at
526
-
527
- http://www.apache.org/licenses/LICENSE-2.0
528
-
529
- Unless required by applicable law or agreed to in writing, software
530
- distributed under the License is distributed on an "AS IS" BASIS,
531
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
532
- See the License for the specific language governing permissions and
533
- limitations under the License.
534
- */
535
-
536
- const unquotedKey = /^(?!__proto__$)[$_\p{ID_Start}][$\p{ID_Continue}]+$|^\d+$/u;
537
- function stringifyKey(key) {
538
- return unquotedKey.test(key) ? key : JSON.stringify(key);
539
- }
540
- function stringifyPropertyAccess(key) {
541
- return unquotedKey.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
542
- }
543
-
544
- /**
545
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
546
- * Changes August 19th 2023 :
547
- * - updated to use subshape for scale decoding
548
- * - adapted from deno to typescript
549
- *
550
- Copyright 2023 Parity Technologies
551
-
552
- Licensed under the Apache License, Version 2.0 (the "License");
553
- you may not use this file except in compliance with the License.
554
- You may obtain a copy of the License at
555
-
556
- http://www.apache.org/licenses/LICENSE-2.0
557
-
558
- Unless required by applicable law or agreed to in writing, software
559
- distributed under the License is distributed on an "AS IS" BASIS,
560
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
561
- See the License for the specific language governing permissions and
562
- limitations under the License.
563
- */
564
-
565
- function normalizeIdent(ident) {
566
- if (ident.startsWith("r#")) ident = ident.slice(2);
567
- return normalizeKeyword(ident.replace(/(?:[^\p{ID_Continue}]|_)+(.)/gu, (_, $1) => $1.toUpperCase()));
568
- }
569
- function normalizeDocs(docs) {
570
- let str = docs?.join("\n") ?? "";
571
- str = str.replace(/[^\S\n]+$/gm, "") // strip trailing whitespace
572
- .replace(/^\n+|\n+$/g, ""); // strip leading and trailing newlines
573
- const match = /^([^\S\n]+).*(?:\n\1.*)*$/.exec(str); // find a common indent
574
- if (match) {
575
- const {
576
- 1: prefix
577
- } = match;
578
- str = str.replace(new RegExp(`^${prefix}`, "gm"), ""); // strip the common indent
579
- // this `new RegExp` is safe because `prefix` must be whitespace
580
- }
581
-
582
- return str;
583
- }
584
- function normalizePackageName(name) {
585
- return name.replace(/[A-Z]/g, x => `-` + x.toLowerCase());
586
- }
587
- function normalizeTypeName(name) {
588
- return normalizeIdent(name).replace(/^./, x => x.toUpperCase());
589
- }
590
- function normalizeVariableName(name) {
591
- return normalizeIdent(name).replace(/^./, x => x.toLowerCase());
592
- }
593
-
594
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words
595
- const keywords = ["break", "case", "catch", "class", "const", "continue", "debugger", "delete", "do", "else", "export", "extends", "false", "finally", "for", "function", "if", "import", "in", "instanceof", "new", "null", "return", "super", "switch", "this", "throw", "true", "try", "typeof", "var", "void", "while", "with", "let", "static", "yield", "await", "enum", "implements", "interface", "package", "private", "protected", "public"];
596
- function normalizeKeyword(ident) {
597
- return keywords.includes(ident) ? ident + "_" : ident;
598
- }
599
-
600
- /**
601
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
602
- * Changes August 19th 2023 :
603
- * - updated to use subshape for scale decoding
604
- * - adapted from deno to typescript
605
- *
606
- Copyright 2023 Parity Technologies
607
-
608
- Licensed under the Apache License, Version 2.0 (the "License");
609
- you may not use this file except in compliance with the License.
610
- You may obtain a copy of the License at
611
-
612
- http://www.apache.org/licenses/LICENSE-2.0
613
-
614
- Unless required by applicable law or agreed to in writing, software
615
- distributed under the License is distributed on an "AS IS" BASIS,
616
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
617
- See the License for the specific language governing permissions and
618
- limitations under the License.
619
- */
620
-
621
- function getOrInit(container, key, init) {
622
- let value = container.get(key);
623
- if (value === undefined) {
624
- value = init();
625
- container.set(key, value);
626
- }
627
- return value;
628
- }
629
-
630
- // export class WeakRefMap<K, V extends object> {
631
- // map = new Map<K, WeakRef<V>>()
632
- // finReg = new FinalizationRegistry<K>((key) => this.map.delete(key))
633
- // get(key: K) {
634
- // return this.map.get(key)?.deref()
635
- // }
636
- // set(key: K, value: V) {
637
- // this.map.set(key, new WeakRef(value))
638
- // this.finReg.register(value, key, value)
639
- // }
640
- // delete(key: K) {
641
- // const value = this.get(key)
642
- // if (!value) return false
643
- // this.map.delete(key)
644
- // this.finReg.unregister(value)
645
- // return true
646
- // }
647
- // }
648
-
649
- /**
650
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
651
- * Changes August 19th 2023 :
652
- * - updated to use subshape for scale decoding
653
- * - adapted from deno to typescript
654
- *
655
- Copyright 2023 Parity Technologies
656
-
657
- Licensed under the Apache License, Version 2.0 (the "License");
658
- you may not use this file except in compliance with the License.
659
- You may obtain a copy of the License at
660
-
661
- http://www.apache.org/licenses/LICENSE-2.0
9
+ /** Constant: https://docs.substrate.io/build/application-development/#metadata-format */
10
+ const magicNumber = 1635018093;
662
11
 
663
- Unless required by applicable law or agreed to in writing, software
664
- distributed under the License is distributed on an "AS IS" BASIS,
665
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
666
- See the License for the specific language governing permissions and
667
- limitations under the License.
668
- */
12
+ var packageJson = {
13
+ name: "@talismn/scale"};
669
14
 
670
- class ChainError extends Error {
671
- name = "ChainError";
672
- constructor(value) {
673
- super();
674
- this.value = value;
675
- this.stack = "ChainError: see error.value\n [error occurred on chain]";
676
- }
677
- static toArgs = x => [x.value];
678
- }
15
+ var log = anylogger(packageJson.name);
679
16
 
680
17
  /**
681
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
682
- * Changes August 19th 2023 :
683
- * - updated to use subshape for scale decoding
684
- * - adapted from deno to typescript
18
+ * Converts a `Metadata` into a `MiniMetadata`.
685
19
  *
686
- Copyright 2023 Parity Technologies
687
-
688
- Licensed under the Apache License, Version 2.0 (the "License");
689
- you may not use this file except in compliance with the License.
690
- You may obtain a copy of the License at
691
-
692
- http://www.apache.org/licenses/LICENSE-2.0
693
-
694
- Unless required by applicable law or agreed to in writing, software
695
- distributed under the License is distributed on an "AS IS" BASIS,
696
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
697
- See the License for the specific language governing permissions and
698
- limitations under the License.
699
- */
700
- // eslint-disable-next-line @typescript-eslint/no-namespace
701
- let Era;
702
- (function (_Era) {
703
- _Era.Immortal = {
704
- type: "Immortal"
705
- };
706
- function Mortal(period, current) {
707
- const adjustedPeriod = minN(maxN(nextPowerOfTwo(period), 4n), 1n << 16n);
708
- const phase = current % adjustedPeriod;
709
- const quantizeFactor = maxN(adjustedPeriod >> 12n, 1n);
710
- const quantizedPhase = phase / quantizeFactor * quantizeFactor;
711
- return {
712
- type: "Mortal",
713
- period: adjustedPeriod,
714
- phase: quantizedPhase
715
- };
716
- }
717
- _Era.Mortal = Mortal;
718
- })(Era || (Era = {}));
719
- const $era = $.createShape({
720
- metadata: $.metadata("$era"),
721
- staticSize: 2,
722
- subEncode(buffer, value) {
723
- if (value.type === "Immortal") {
724
- buffer.array[buffer.index++] = 0;
725
- } else {
726
- const quantizeFactor = maxN(value.period >> 12n, 1n);
727
- const encoded = minN(maxN(trailingZeroes(value.period) - 1n, 1n), 15n) | value.phase / quantizeFactor << 4n;
728
- $.u16.subEncode(buffer, Number(encoded));
729
- }
730
- },
731
- subDecode(buffer) {
732
- if (buffer.array[buffer.index] === 0) {
733
- buffer.index++;
734
- return {
735
- type: "Immortal"
736
- };
737
- } else {
738
- const encoded = BigInt($.u16.subDecode(buffer));
739
- const period = 2n << encoded % (1n << 4n);
740
- const quantizeFactor = maxN(period >> 12n, 1n);
741
- const phase = (encoded >> 4n) * quantizeFactor;
742
- if (period >= 4n && phase <= period) {
743
- return {
744
- type: "Mortal",
745
- period,
746
- phase
747
- };
748
- } else {
749
- throw new Error("Invalid period and phase");
750
- }
751
- }
752
- },
753
- subAssert: $.taggedUnion("type", [$.variant("Immortal"), $.variant("Mortal", $.field("period", $.u64), $.field("phase", $.u64))]).subAssert
754
- });
755
- function maxN(a, b) {
756
- return a > b ? a : b;
757
- }
758
- function minN(a, b) {
759
- return a < b ? a : b;
760
- }
761
- function trailingZeroes(n) {
762
- let i = 0n;
763
- while (!(n & 1n)) {
764
- i++;
765
- n >>= 1n;
766
- }
767
- return i;
768
- }
769
- function nextPowerOfTwo(n) {
770
- n--;
771
- let p = 1n;
772
- while (n > 0n) {
773
- p <<= 1n;
774
- n >>= 1n;
775
- }
776
- return p;
777
- }
778
-
779
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
780
- const isResult = new $.ShapeVisitor().add($.result, () => true).fallback(() => false);
781
- const isOption = new $.ShapeVisitor().add($.option, () => true).fallback(() => false);
782
- const overrides = {
783
- "Option": (ty, visit) => {
784
- let $some = visit(ty.params[0].ty);
785
- if (isOption.visit($some)) {
786
- $some = $.tuple($some);
787
- }
788
- return $.option($some);
789
- },
790
- "Result": (ty, visit) => {
791
- let $ok = visit(ty.params[0].ty);
792
- if (isResult.visit($ok)) {
793
- $ok = $.tuple($ok);
794
- }
795
- return $.result($ok, $.instance(ChainError, $.tuple(visit(ty.params[1].ty)), ChainError.toArgs));
796
- },
797
- "BTreeMap": (ty, visit) => {
798
- return $.map(visit(ty.params[0].ty), visit(ty.params[1].ty));
799
- },
800
- "BTreeSet": (ty, visit) => {
801
- return $.set(visit(ty.params[0].ty));
802
- },
803
- "frame_support::traits::misc::WrapperOpaque": (ty, visit) => {
804
- return $.lenPrefixed(visit(ty.params[0].ty));
805
- },
806
- "frame_support::traits::misc::WrapperKeepOpaque": (ty, visit) => {
807
- return $.lenPrefixed(visit(ty.params[0].ty));
808
- },
809
- "sp_runtime::generic::era::Era": () => {
810
- return $era;
811
- }
812
- };
813
-
814
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
815
- /**
816
- * All derived codecs for ZSTs will use this exact codec,
817
- * so `derivedCodec === $null` is true iff the type is a ZST.
818
- */
819
- const $null = $.withMetadata($.metadata("$null"), $.constant(null));
820
- function transformTys(tys) {
821
- const tysMap = new Map(tys.map(ty => [ty.id, ty]));
822
- const memo = new Map();
823
- const types = {};
824
- const paths = {};
825
- const seenPaths = new Map();
826
- const includePaths = new Set();
827
- const names = new Map();
828
- const nameCounts = new Map();
829
- for (const ty of tys) {
830
- const path = ty.path.join("::");
831
- if (!path) continue;
832
- const last = seenPaths.get(path);
833
- if (last !== undefined) {
834
- if (last === null || !eqTy(tysMap, last.id, ty.id)) {
835
- seenPaths.set(path, null);
836
- includePaths.delete(path);
837
- }
838
- continue;
839
- }
840
- seenPaths.set(path, ty);
841
- includePaths.add(path);
842
- }
843
- for (const path of includePaths) {
844
- const parts = path.split("::");
845
- const name = parts.at(-1);
846
- const map = getOrInit(nameCounts, name, () => new Map());
847
- for (let i = 0; i < parts.length; i++) {
848
- const pathPart = parts.slice(0, i).join("::");
849
- map.set(pathPart, (map.get(pathPart) ?? 0) + 1);
850
- }
851
- }
852
- for (const path of includePaths) {
853
- const parts = path.split("::");
854
- const name = parts.at(-1);
855
- const map = nameCounts.get(name);
856
- const pathLength = parts.findIndex((_, i) => map.get(parts.slice(0, i).join("::")) === 1);
857
- const newPath = [...parts.slice(0, pathLength), name].join("::");
858
- const newName = normalizeTypeName(newPath);
859
- names.set(path, newName);
860
- }
861
- return {
862
- ids: tys.map(ty => visit(ty.id)),
863
- types,
864
- paths
865
- };
866
- function visit(i) {
867
- return getOrInit(memo, i, () => {
868
- memo.set(i, $.deferred(() => memo.get(i)));
869
- const ty = tysMap.get(i);
870
- const path = ty.path.join("::");
871
- const usePath = includePaths.has(path);
872
- const name = names.get(path);
873
- if (usePath && types[name]) return types[name];
874
- const codec = withDocs(ty.docs, _visit(ty));
875
- if (usePath) return types[name] ??= paths[path] = codec;
876
- return codec;
877
- });
878
- }
879
- function _visit(ty) {
880
- const overrideFn = overrides[ty.path.join("::")];
881
- if (overrideFn) return overrideFn(ty, visit);
882
- if (ty.type === "Struct") {
883
- if (ty.fields.length === 0) {
884
- return $null;
885
- } else if (ty.fields[0].name === undefined) {
886
- if (ty.fields.length === 1) {
887
- // wrapper
888
- return visit(ty.fields[0].ty);
889
- } else {
890
- return $.tuple(...ty.fields.map(x => visit(x.ty)));
891
- }
892
- } else {
893
- return $.object(...ty.fields.map(x => withDocs(x.docs, maybeOptionalField(normalizeIdent(x.name), visit(x.ty)))));
894
- }
895
- } else if (ty.type === "Tuple") {
896
- if (ty.fields.length === 0) {
897
- return $null;
898
- } else if (ty.fields.length === 1) {
899
- // wrapper
900
- return visit(ty.fields[0]);
901
- } else {
902
- return $.tuple(...ty.fields.map(x => visit(x)));
903
- }
904
- } else if (ty.type === "Union") {
905
- if (ty.members.length === 0) {
906
- return $.never;
907
- } else if (ty.members.every(x => x.fields.length === 0)) {
908
- const members = {};
909
- for (const {
910
- index,
911
- name
912
- } of ty.members) {
913
- members[index] = normalizeIdent(name);
914
- }
915
- return $.literalUnion(members);
916
- } else {
917
- const members = {};
918
- for (const {
919
- fields,
920
- name,
921
- index
922
- } of ty.members) {
923
- let member;
924
- const type = normalizeIdent(name);
925
- if (fields.length === 0) {
926
- member = $.variant(type);
927
- } else if (fields[0].name === undefined) {
928
- // Tuple variant
929
- const $value = fields.length === 1 ? visit(fields[0].ty) : $.tuple(...fields.map(f => visit(f.ty)));
930
- member = $.variant(type, maybeOptionalField("value", $value));
931
- } else {
932
- // Object variant
933
- const memberFields = fields.map(field => {
934
- return withDocs(field.docs, maybeOptionalField(normalizeIdent(field.name), visit(field.ty)));
935
- });
936
- member = $.variant(type, ...memberFields);
937
- }
938
- members[index] = member;
939
- }
940
- return $.taggedUnion("type", members);
941
- }
942
- } else if (ty.type === "Sequence") {
943
- const $inner = visit(ty.typeParam);
944
- if ($inner === $.u8) {
945
- return $.uint8Array;
946
- } else {
947
- return $.array($inner);
948
- }
949
- } else if (ty.type === "SizedArray") {
950
- const $inner = visit(ty.typeParam);
951
- if ($inner === $.u8) {
952
- return $.sizedUint8Array(ty.len);
953
- } else {
954
- return $.sizedArray($inner, ty.len);
955
- }
956
- } else if (ty.type === "Primitive") {
957
- if (ty.kind === "char") return $.str;
958
- return $[ty.kind];
959
- } else if (ty.type === "Compact") {
960
- return $.compact(visit(ty.typeParam));
961
- } else if (ty.type === "BitSequence") {
962
- return $.bitSequence;
963
- } else {
964
- throw new Error("unreachable");
965
- }
966
- }
967
- }
968
- function withDocs(_docs, codec) {
969
- const docs = normalizeDocs(_docs);
970
- if (docs) return $.documented(docs, codec);
971
- return codec;
972
- }
973
- function eqTy(tysMap, a, b) {
974
- const seen = new Set();
975
- return eqTy(a, b);
976
- function eqTy(ai, bi) {
977
- const key = `${ai}=${bi}`;
978
- if (seen.has(key)) return true;
979
- seen.add(key);
980
- const a = tysMap.get(ai);
981
- const b = tysMap.get(bi);
982
- if (a.id === b.id) return true;
983
- if (a.type !== b.type) return false;
984
- if (a.path.join("::") !== b.path.join("::")) return false;
985
- if (normalizeDocs(a.docs) !== normalizeDocs(b.docs)) return false;
986
- if (!eqArray(a.params, b.params, (a, b) => a.name === b.name && a.ty == null === (b.ty == null) && (a.ty == null || eqTy(a.ty, b.ty)))) {
987
- return false;
988
- }
989
- if (a.type === "BitSequence") {
990
- return true;
991
- }
992
- if (a.type === "Primitive" && b.type === "Primitive") {
993
- return a.kind === b.kind;
994
- }
995
- if (a.type === "Compact" && b.type === "Compact" || a.type === "Sequence" && b.type === "Sequence") {
996
- return eqTy(a.typeParam, b.typeParam);
997
- }
998
- if (a.type === "SizedArray" && b.type === "SizedArray") {
999
- return a.len === b.len && eqTy(a.typeParam, b.typeParam);
1000
- }
1001
- if (a.type === "Struct" && b.type === "Struct") {
1002
- return eqArray(a.fields, b.fields, eqField);
1003
- }
1004
- if (a.type === "Tuple" && b.type === "Tuple") {
1005
- return eqArray(a.fields, b.fields, eqTy);
1006
- }
1007
- if (a.type === "Union" && b.type === "Union") {
1008
- return eqArray(a.members, b.members, (a, b) => a.index === b.index && a.name === b.name && normalizeDocs(a.docs) === normalizeDocs(b.docs) && eqArray(a.fields, b.fields, eqField));
1009
- }
1010
- return false;
1011
- }
1012
- function eqField(a, b) {
1013
- return a.name === b.name && a.typeName === b.typeName && eqDocs(a.docs, b.docs) && eqTy(a.ty, b.ty);
1014
- }
1015
- function eqDocs(a, b) {
1016
- return normalizeDocs(a) === normalizeDocs(b);
1017
- }
1018
- function eqArray(a, b, eqVal) {
1019
- return a.length === b.length && a.every((x, i) => eqVal(x, b[i]));
1020
- }
1021
- }
1022
- const optionInnerVisitor = new $.ShapeVisitor().add($.option, (_codec, $some) => $some).fallback(() => null);
1023
- function maybeOptionalField(key, $value) {
1024
- const $inner = optionInnerVisitor.visit($value);
1025
- return $inner ? $.optionalField(key, $inner) : $.field(key, $value);
1026
- }
1027
-
1028
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
1029
- function $storageKey(palletName, entryName, $key) {
1030
- const palletHash = twox128.hash(new TextEncoder().encode(palletName));
1031
- const entryHash = twox128.hash(new TextEncoder().encode(entryName));
1032
- return $.createShape({
1033
- metadata: $.metadata("$storageKey", $storageKey, palletName, entryName, $key),
1034
- staticSize: $key.staticSize + 32,
1035
- subEncode(buffer, key) {
1036
- buffer.insertArray(palletHash);
1037
- buffer.insertArray(entryHash);
1038
- $key.subEncode(buffer, key);
1039
- },
1040
- subDecode(buffer) {
1041
- // Ignore initial hashes
1042
- buffer.index += 32;
1043
- return $key.subDecode(buffer);
1044
- },
1045
- subAssert(assert) {
1046
- $key.subAssert(assert);
1047
- }
1048
- });
1049
- }
1050
- const $emptyKey = $.withMetadata($.metadata("$emptyKey"), $.constant(undefined));
1051
- const $partialEmptyKey = $.createShape({
1052
- metadata: $.metadata("$partialEmptyKey"),
1053
- staticSize: 0,
1054
- subEncode() {},
1055
- subDecode() {
1056
- throw new Error("Cannot decode partial key");
1057
- },
1058
- subAssert(assert) {
1059
- if (assert.value != null) {
1060
- throw new $.ShapeAssertError(this, assert.value, `${assert.path} != null`);
1061
- }
1062
- }
1063
- });
1064
- function $partialSingleKey($inner) {
1065
- return $.createShape({
1066
- metadata: $.metadata("$partialSingleKey", $partialSingleKey, $inner),
1067
- staticSize: $inner.staticSize,
1068
- subEncode(buffer, key) {
1069
- if (key !== null) $inner.subEncode(buffer, key);
1070
- },
1071
- subDecode() {
1072
- throw new Error("Cannot decode partial key");
1073
- },
1074
- subAssert(assert) {
1075
- if (assert.value === null) return;
1076
- $inner.subAssert(assert);
1077
- }
1078
- });
1079
- }
1080
-
1081
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1082
-
1083
- function $partialMultiKey(...codecs) {
1084
- return $.createShape({
1085
- metadata: $.metadata("$partialMultiKey", $partialMultiKey, ...codecs),
1086
- staticSize: $.tuple(...codecs).staticSize,
1087
- subEncode(buffer, key) {
1088
- if (!key) return;
1089
- for (let i = 0; i < key.length; i++) {
1090
- codecs[i].subEncode(buffer, key[i]);
1091
- }
1092
- },
1093
- subDecode() {
1094
- throw new Error("Cannot decode partial key");
1095
- },
1096
- subAssert(assert) {
1097
- if (assert.value === null) return;
1098
- assert.instanceof(this, Array);
1099
- const assertLength = assert.key(this, "length");
1100
- assertLength.typeof(this, "number");
1101
- const length = assertLength.value;
1102
- $.tuple(...codecs.slice(0, length)).subAssert(assert);
1103
- }
1104
- });
1105
- }
1106
-
1107
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
1108
- const hashers = {
1109
- blake2_128,
1110
- blake2_256,
1111
- blake2_128Concat,
1112
- twox128,
1113
- twox256,
1114
- twox64Concat,
1115
- identity
1116
- };
1117
- const $hasher = $.literalUnion(["blake2_128", "blake2_256", "blake2_128Concat", "twox128", "twox256", "twox64Concat", "identity"]);
1118
- const $storageEntry = $.object($.field("name", $.str), $.field("modifier", $.literalUnion(["Optional", "Default"])), $.taggedUnion("type", [$.variant("Plain", $.field("value", $tyId)), $.variant("Map", $.field("hashers", $.array($hasher)), $.field("key", $tyId), $.field("value", $tyId))]), $.field("default", $.uint8Array), $.field("docs", $.array($.str)));
1119
- const $constant = $.object($.field("name", $.str), $.field("ty", $tyId), $.field("value", $.uint8Array), $.field("docs", $.array($.str)));
1120
- const $pallet = $.object($.field("name", $.str), $.optionalField("storage", $.object($.field("prefix", $.str), $.field("entries", $.array($storageEntry)))), $.optionalField("calls", $tyId), $.optionalField("event", $tyId), $.field("constants", $.array($constant)), $.optionalField("error", $tyId), $.field("id", $.u8));
1121
- const $extrinsicDef = $.object($.field("ty", $tyId), $.field("version", $.u8), $.field("signedExtensions", $.array($.object($.field("ident", $.str), $.field("ty", $tyId), $.field("additionalSigned", $tyId)))));
1122
-
1123
- // https://docs.substrate.io/build/application-development/#metadata-system
1124
- const magicNumber = 1635018093;
1125
- const $metadata = $.object($.field("magicNumber", $.constant(magicNumber, $.u32)), $.field("version", $.constant(14, $.u8)), $.field("tys", $.array($ty)), $.field("pallets", $.array($pallet)), $.field("extrinsic", $extrinsicDef),
1126
- // TODO: is this useful?
1127
- $.field("runtime", $tyId));
1128
- function transformMetadata(metadata) {
1129
- const {
1130
- ids,
1131
- types,
1132
- paths
1133
- } = transformTys(metadata.tys);
1134
- return {
1135
- types,
1136
- paths,
1137
- pallets: Object.fromEntries(metadata.pallets.map(pallet => [pallet.name, {
1138
- id: pallet.id,
1139
- name: pallet.name,
1140
- storagePrefix: pallet.storage?.prefix ?? pallet.name,
1141
- storage: Object.fromEntries(pallet.storage?.entries.map(storage => {
1142
- let key, partialKey;
1143
- if (storage.type === "Plain") {
1144
- key = $emptyKey;
1145
- partialKey = $partialEmptyKey;
1146
- } else if (storage.hashers.length === 1) {
1147
- key = hashers[storage.hashers[0]].$hash(ids[storage.key]);
1148
- partialKey = $partialSingleKey(key);
1149
- } else {
1150
- const codecs = extractTupleMembersVisitor.visit(ids[storage.key]).map((codec, i) => hashers[storage.hashers[i]].$hash(codec));
1151
- key = $.tuple(...codecs);
1152
- partialKey = $partialMultiKey(...codecs);
1153
- }
1154
- return [storage.name, {
1155
- singular: storage.type === "Plain",
1156
- name: storage.name,
1157
- key: $storageKey(pallet.name, storage.name, key),
1158
- partialKey: $storageKey(pallet.name, storage.name, partialKey),
1159
- value: ids[storage.value],
1160
- docs: normalizeDocs(storage.docs),
1161
- default: storage.modifier === "Default" ? storage.default : undefined
1162
- }];
1163
- }) ?? []),
1164
- constants: Object.fromEntries(pallet.constants.map(constant => [constant.name, {
1165
- name: constant.name,
1166
- codec: ids[constant.ty],
1167
- value: constant.value,
1168
- docs: normalizeDocs(constant.docs)
1169
- }])),
1170
- types: {
1171
- call: ids[pallet.calls],
1172
- error: ids[pallet.error],
1173
- event: ids[pallet.event]
1174
- },
1175
- docs: ""
1176
- }])),
1177
- extrinsic: {
1178
- call: getExtrinsicParameter("call"),
1179
- signature: getExtrinsicParameter("signature"),
1180
- address: getExtrinsicParameter("address"),
1181
- extra: getExtensionsCodec("ty"),
1182
- additional: getExtensionsCodec("additionalSigned")
1183
- }
1184
- };
1185
- function getExtrinsicParameter(key) {
1186
- if (!metadata.extrinsic.ty) return $.never;
1187
- const extrinsicTy = metadata.tys[metadata.extrinsic.ty];
1188
- if (!extrinsicTy) return $.never;
1189
- const id = extrinsicTy.params.find(x => x.name.toLowerCase() === key)?.ty;
1190
- if (id === undefined) return $.never;
1191
- return ids[id];
1192
- }
1193
- function getExtensionsCodec(key) {
1194
- return $.object(...metadata.extrinsic.signedExtensions.flatMap(ext => {
1195
- const codec = ids[ext[key]];
1196
- if (codec === $null) return [];
1197
- return [$.field(normalizeIdent(ext.ident), codec)];
1198
- }) // eslint-disable-line @typescript-eslint/no-explicit-any
1199
- );
1200
- }
1201
- }
1202
-
1203
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1204
- const extractTupleMembersVisitor = new $.ShapeVisitor().add(
1205
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1206
- $.tuple, (_codec, ...members) => members);
1207
-
1208
- /**
1209
- * Adapted from https://github.com/paritytech/capi-old copyright Parity Technologies (APACHE License 2.0)
1210
- * Changes August 19th 2023 :
1211
- * - updated to use subshape for scale decoding
1212
- * - adapted from deno to typescript
20
+ * A `MiniMetadata` only contains the types inside of its `lookup` which are relevant for
21
+ * the storage queries specified in `palletsAndItems`.
1213
22
  *
1214
- Copyright 2023 Parity Technologies
1215
-
1216
- Licensed under the Apache License, Version 2.0 (the "License");
1217
- you may not use this file except in compliance with the License.
1218
- You may obtain a copy of the License at
1219
-
1220
- http://www.apache.org/licenses/LICENSE-2.0
1221
-
1222
- Unless required by applicable law or agreed to in writing, software
1223
- distributed under the License is distributed on an "AS IS" BASIS,
1224
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1225
- See the License for the specific language governing permissions and
1226
- limitations under the License.
23
+ * E.g. if `palletsAndItems` is `{ pallet: "System", items: ["Account"] }`, then only the
24
+ * types used in the `System.Account` storage query will remain inside of metadata.lookups.
1227
25
  */
1228
- function decodeMetadata(encoded) {
1229
- return transformMetadata($metadata.decode(encoded));
1230
- }
1231
- const $metadataV14 = $metadata;
1232
-
1233
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
1234
- function $extrinsic(metadata) {
1235
- const $sig = metadata.extrinsic.signature;
1236
- const $sigPromise = $.promise($sig);
1237
- const $call = metadata.extrinsic.call;
1238
- const $address = metadata.extrinsic.address;
1239
- const $extra = metadata.extrinsic.extra;
1240
- const $additional = metadata.extrinsic.additional;
1241
- const toSignSize = $call.staticSize + $extra.staticSize + $additional.staticSize;
1242
- const totalSize = 1 + $address.staticSize + $sig.staticSize + toSignSize;
1243
- const $baseExtrinsic = $.createShape({
1244
- metadata: [],
1245
- staticSize: totalSize,
1246
- subEncode(buffer, extrinsic) {
1247
- const firstByte = +!!extrinsic.signature << 7 | extrinsic.protocolVersion;
1248
- buffer.array[buffer.index++] = firstByte;
1249
- const {
1250
- signature,
1251
- call
1252
- } = extrinsic;
1253
- if (signature) {
1254
- $address.subEncode(buffer, signature.sender.address);
1255
- if (signature.additional) {
1256
- const toSignBuffer = new $.EncodeBuffer(buffer.stealAlloc(toSignSize));
1257
- $call.subEncode(toSignBuffer, call);
1258
- const callEnd = toSignBuffer.finishedSize + toSignBuffer.index;
1259
- $extra.subEncode(toSignBuffer, signature.extra);
1260
- const extraEnd = toSignBuffer.finishedSize + toSignBuffer.index;
1261
- $additional.subEncode(toSignBuffer, signature.additional);
1262
- const toSignEncoded = toSignBuffer.finish();
1263
- const callEncoded = toSignEncoded.subarray(0, callEnd);
1264
- const extraEncoded = toSignEncoded.subarray(callEnd, extraEnd);
1265
- const toSign = toSignEncoded.length > 256 ? blake2_256.hash(toSignEncoded) : toSignEncoded;
1266
- const sig = signature.sender.sign(toSign, toSignEncoded);
1267
- if (sig instanceof Promise) {
1268
- $sigPromise.subEncode(buffer, sig);
1269
- } else {
1270
- $sig.subEncode(buffer, sig);
1271
- }
1272
- buffer.insertArray(extraEncoded);
1273
- buffer.insertArray(callEncoded);
1274
- } else {
1275
- $sig.subEncode(buffer, signature.sig);
1276
- $extra.subEncode(buffer, signature.extra);
1277
- $call.subEncode(buffer, call);
1278
- }
1279
- } else {
1280
- $call.subEncode(buffer, call);
1281
- }
1282
- },
1283
- subDecode(buffer) {
1284
- const firstByte = buffer.array[buffer.index++];
1285
- const hasSignature = firstByte & 1 << 7;
1286
- const protocolVersion = firstByte & ~(1 << 7);
1287
- let signature;
1288
- if (hasSignature) {
1289
- const address = $address.subDecode(buffer);
1290
- const sig = $sig.subDecode(buffer);
1291
- const extra = $extra.subDecode(buffer);
1292
- signature = {
1293
- sender: {
1294
- address
1295
- },
1296
- sig,
1297
- extra
1298
- };
1299
- }
1300
- const call = $call.subDecode(buffer);
1301
- return {
1302
- protocolVersion,
1303
- signature,
1304
- call
1305
- };
1306
- },
1307
- subAssert(assert) {
1308
- assert.typeof(this, "object");
1309
- assert.key(this, "protocolVersion").equals($.u8, 4);
1310
- const value_ = assert.value;
1311
- $call.subAssert(assert.key(this, "call"));
1312
- if (value_.signature) {
1313
- const signatureAssertState = assert.key(this, "signature");
1314
- $address.subAssert(signatureAssertState.key(this, "sender").key(this, "address"));
1315
- $extra.subAssert(signatureAssertState.key(this, "extra"));
1316
- if ("additional" in value_.signature) {
1317
- $additional.subAssert(signatureAssertState.key(this, "additional"));
1318
- signatureAssertState.key(this, "sender").key(this, "sign").typeof(this, "function");
1319
- } else {
1320
- $sig.subAssert(signatureAssertState.key(this, "sig"));
1321
- }
1322
- }
1323
- }
1324
- });
1325
- return $.withMetadata($.metadata("$extrinsic", $extrinsic, metadata), $.lenPrefixed($baseExtrinsic));
1326
- }
1327
- class SignerError extends Error {
1328
- name = "SignerError";
1329
- constructor(inner) {
1330
- super();
1331
- this.inner = inner;
1332
- }
1333
- }
1334
-
1335
- var packageJson = {
1336
- name: "@talismn/scale",
1337
- version: "0.0.2",
1338
- author: "Talisman",
1339
- homepage: "https://talisman.xyz",
1340
- license: "GPL-3.0-or-later",
1341
- publishConfig: {
1342
- access: "public"
1343
- },
1344
- repository: {
1345
- directory: "packages/scale",
1346
- type: "git",
1347
- url: "https://github.com/talismansociety/talisman.git"
1348
- },
1349
- main: "dist/talismn-scale.cjs.js",
1350
- module: "dist/talismn-scale.esm.js",
1351
- files: [
1352
- "/dist"
1353
- ],
1354
- engines: {
1355
- node: ">=18"
1356
- },
1357
- scripts: {
1358
- test: "jest",
1359
- lint: "eslint src --max-warnings 0",
1360
- clean: "rm -rf dist && rm -rf .turbo rm -rf node_modules"
1361
- },
1362
- dependencies: {
1363
- "@talismn/subshape-fork": "^0.0.2",
1364
- "@talismn/util": "workspace:*",
1365
- anylogger: "^1.0.11",
1366
- "wasm-feature-detect": "^1.6.1",
1367
- "wat-the-crypto": "^0.0.3"
1368
- },
1369
- devDependencies: {
1370
- "@polkadot/util-crypto": "^12.3.2",
1371
- "@talismn/eslint-config": "workspace:*",
1372
- "@talismn/tsconfig": "workspace:*",
1373
- "@types/jest": "^27.5.1",
1374
- eslint: "^8.52.0",
1375
- jest: "^29.7",
1376
- "ts-jest": "^29.1.1",
1377
- typescript: "^5.2.2"
1378
- },
1379
- peerDependencies: {
1380
- "@polkadot/util-crypto": "12.x"
1381
- },
1382
- eslintConfig: {
1383
- root: true,
1384
- "extends": [
1385
- "@talismn/eslint-config/base"
1386
- ]
1387
- }
1388
- };
1389
-
1390
- var log = anylogger(packageJson.name);
1391
-
1392
- const getMetadataVersion = metadataRpc => {
1393
- // https://docs.substrate.io/build/application-development/#metadata-system
1394
- const magicNumber = 1635018093;
1395
- const {
1396
- version
1397
- } = $.object($.field("magicNumber", $.constant(magicNumber, $.u32)), $.field("version", $.u8)).decode($.decodeHex(metadataRpc));
1398
- return version;
1399
- };
1400
- const filterMetadataPalletsAndItems = (metadata, palletsAndItems, extraKeepTypes) => {
26
+ const compactMetadata = (metadata, palletsAndItems = [], runtimeApisAndMethods = [], extraKeepTypes = []) => {
1401
27
  // remove pallets we don't care about
1402
28
  metadata.pallets = metadata.pallets.filter(pallet =>
1403
29
  // keep this pallet if it's listed in `palletsAndItems`
1404
30
  palletsAndItems.some(({
1405
- pallet: palletFilter
1406
- }) => palletFilter(pallet)));
31
+ pallet: palletName
32
+ }) => pallet.name === palletName));
1407
33
 
1408
34
  // remove fields we don't care about from each pallet, and extract types for each storage item we care about
1409
- const items = palletsAndItems.flatMap(({
1410
- pallet: palletFilter,
1411
- items
35
+ const palletsKeepTypes = palletsAndItems.flatMap(({
36
+ pallet: palletName,
37
+ constants: constantNames,
38
+ items: itemNames
1412
39
  }) => {
1413
- const pallet = metadata.pallets.find(palletFilter);
1414
- if (!pallet || !pallet.storage) {
1415
- log.debug("Failed to find pallet", palletFilter);
40
+ const pallet = metadata.pallets.find(pallet => pallet.name === palletName);
41
+ if (!pallet) {
42
+ log.debug("Failed to find pallet", palletName);
1416
43
  return [];
1417
44
  }
1418
45
 
1419
- // remove fields we don't care about
46
+ // remove pallet fields we don't care about
1420
47
  pallet.calls = undefined;
1421
- pallet.constants = [];
1422
- pallet.error = undefined;
1423
- pallet.event = undefined;
48
+ pallet.constants = constantNames ? pallet.constants.filter(constant => constantNames.includes(constant.name)) : [];
49
+ // v15 (NOT v14) has docs
50
+ if ("docs" in pallet) pallet.docs = [];
51
+ pallet.errors = undefined;
52
+ pallet.events = undefined;
53
+ if (!pallet.storage) return [];
1424
54
 
1425
55
  // filter and extract storage items we care about
1426
- pallet.storage.entries = pallet.storage.entries.filter(item => items.some(itemFilter => itemFilter(item)));
1427
- return pallet.storage.entries;
56
+ pallet.storage.items = pallet.storage.items.filter(item => itemNames.some(itemName => item.name === itemName));
57
+ return [...pallet.storage.items.flatMap(item => [
58
+ // each type can be either "Plain" or "Map"
59
+ // if it's "Plain" we only need to get the value type
60
+ // if it's a "Map" we want to keep both the key AND the value types
61
+ item.type.tag === "plain" && item.type.value, item.type.tag === "map" && item.type.value.key, item.type.tag === "map" && item.type.value.value]).filter(type => typeof type === "number"), ...pallet.constants.flatMap(constant => constant.type)];
1428
62
  });
1429
63
 
1430
- // this is a set of type ids which we plan to keep in our mutated metadata
64
+ // remove runtime apis we don't care about
65
+ let runtimeApisKeepTypes = [];
66
+ if ("apis" in metadata) {
67
+ // metadata is v15 (NOT v14)
68
+
69
+ // keep this api if it's listed in `runtimeApisAndMethods`
70
+ metadata.apis = metadata.apis.filter(runtimeApi => runtimeApisAndMethods.some(({
71
+ runtimeApi: runtimeApiName
72
+ }) => runtimeApi.name === runtimeApiName));
73
+
74
+ // remove methods we don't care about from each runtime api, and extract types for each call's params and result
75
+ runtimeApisKeepTypes = runtimeApisAndMethods.flatMap(({
76
+ runtimeApi: runtimeApiName,
77
+ methods: methodNames
78
+ }) => {
79
+ const runtimeApi = metadata.apis.find(runtimeApi => runtimeApi.name === runtimeApiName);
80
+ if (!runtimeApi) {
81
+ log.debug("Failed to find runtimeApi", runtimeApiName);
82
+ return [];
83
+ }
84
+
85
+ // remove runtime fields we don't care about
86
+ runtimeApi.docs = [];
87
+ if (!runtimeApi.methods) return [];
88
+
89
+ // filter and extract methods we care about
90
+ runtimeApi.methods = runtimeApi.methods.filter(method => methodNames.some(methodName => method.name === methodName));
91
+ return runtimeApi.methods.flatMap(method => [
92
+ // each method has an array of input types (for the params)
93
+ ...method.inputs.map(input => input.type),
94
+ // and one output type (for the result)
95
+ method.output]);
96
+ });
97
+ }
98
+
99
+ // this is a set of type ids which we plan to keep in our compacted metadata
1431
100
  // anything not in this set will be deleted
1432
101
  // we start off with just the types of the state calls we plan to make,
1433
102
  // then we run those types through a function (addDependentTypes) which will also include
1434
103
  // all of the types which those types depend on - recursively
1435
- const keepTypes = new Set(items.flatMap(item => [
1436
- // each type can be either "Plain" or "Map"
1437
- // if it's "Plain" we only need to get the value type
1438
- // if it's a "Map" we want to keep both the key AND the value types
1439
- item.type === "Map" && item.key, item.value]).filter(type => typeof type === "number"));
104
+ const keepTypes = new Set([...palletsKeepTypes, ...runtimeApisKeepTypes]);
1440
105
  extraKeepTypes?.forEach(type => keepTypes.add(type));
1441
106
 
1442
107
  // recursively find all the types which our keepTypes depend on and add them to the keepTypes set
1443
- const metadataTysMap = new Map(metadata.tys.map(ty => [ty.id, ty]));
108
+ const metadataTysMap = new Map(metadata.lookup.map(ty => [ty.id, ty]));
1444
109
  addDependentTypes(metadataTysMap, keepTypes, [...keepTypes]);
1445
110
 
1446
111
  // ditch the types we aren't keeping
1447
- metadata.tys = metadata.tys.filter(type => keepTypes.has(type.id));
112
+ metadata.lookup = metadata.lookup.filter(type => keepTypes.has(type.id));
113
+
114
+ // update all type ids to be sequential (fill the gaps left by the deleted types)
115
+ const newTypeIds = new Map();
116
+ metadata.lookup.forEach((type, index) => newTypeIds.set(type.id, index));
117
+ const getNewTypeId = oldTypeId => {
118
+ const newTypeId = newTypeIds.get(oldTypeId);
119
+ if (typeof newTypeId !== "number") log.error(`Failed to find newTypeId for type ${oldTypeId}`);
120
+ return newTypeId ?? 0;
121
+ };
122
+ remapTypeIds(metadata, getNewTypeId);
123
+ if ("address" in metadata.extrinsic) {
124
+ // metadata is v15 (NOT v14)
125
+ metadata.extrinsic.address = 0;
126
+ metadata.extrinsic.call = 0;
127
+ metadata.extrinsic.extra = 0;
128
+ metadata.extrinsic.signature = 0;
129
+ }
130
+ metadata.extrinsic.signedExtensions = [];
131
+ if ("outerEnums" in metadata) {
132
+ // metadata is v15 (NOT v14)
133
+ metadata.outerEnums.call = 0;
134
+ metadata.outerEnums.error = 0;
135
+ metadata.outerEnums.event = 0;
136
+ }
1448
137
  };
1449
138
  const addDependentTypes = (metadataTysMap, keepTypes, types,
1450
139
  // Prevent stack overflow when a type references itself
@@ -1459,242 +148,240 @@ addedTypes = new Set()) => {
1459
148
  if (addedTypes.has(type.id)) continue;
1460
149
  keepTypes.add(type.id);
1461
150
  addedTypes.add(type.id);
1462
- switch (type.type) {
1463
- case "Struct":
1464
- addDependentSubTypes([...type.params.map(param => param.ty).filter(ty => typeof ty === "number"), ...type.fields.map(field => field.ty).filter(ty => typeof ty === "number")]);
151
+ const paramTypes = type.params.map(param => param.type).filter(type => typeof type === "number");
152
+ addDependentSubTypes(paramTypes);
153
+ switch (type.def.tag) {
154
+ case "array":
155
+ addDependentSubTypes([type.def.value.type]);
1465
156
  break;
1466
- case "Union":
1467
- addDependentSubTypes([...type.params.map(param => param.ty).filter(ty => typeof ty === "number"), ...type.members.flatMap(member => member.fields.map(field => field.ty)).filter(ty => typeof ty === "number")]);
157
+ case "bitSequence":
158
+ addDependentSubTypes([type.def.value.bitOrderType, type.def.value.bitStoreType]);
1468
159
  break;
1469
- case "Sequence":
1470
- addDependentSubTypes([...type.params.map(param => param.ty).filter(ty => typeof ty === "number"), type.typeParam]);
160
+ case "compact":
161
+ addDependentSubTypes([type.def.value]);
1471
162
  break;
1472
- case "SizedArray":
1473
- addDependentSubTypes([...type.params.map(param => param.ty).filter(ty => typeof ty === "number"), type.typeParam]);
163
+ case "composite":
164
+ addDependentSubTypes(type.def.value.map(field => field.type).filter(type => typeof type === "number"));
1474
165
  break;
1475
- case "Tuple":
1476
- addDependentSubTypes([...type.params.map(param => param.ty).filter(ty => typeof ty === "number"), ...type.fields.filter(ty => typeof ty === "number")]);
166
+ case "primitive":
1477
167
  break;
1478
- case "Primitive":
1479
- addDependentSubTypes([...type.params.map(param => param.ty).filter(ty => typeof ty === "number")]);
168
+ case "sequence":
169
+ addDependentSubTypes([type.def.value]);
1480
170
  break;
1481
- case "Compact":
1482
- addDependentSubTypes([...type.params.map(param => param.ty).filter(ty => typeof ty === "number"), type.typeParam]);
171
+ case "tuple":
172
+ addDependentSubTypes(type.def.value.filter(type => typeof type === "number"));
1483
173
  break;
1484
- case "BitSequence":
1485
- addDependentSubTypes([type.bitOrderType, type.bitStoreType]);
174
+ case "variant":
175
+ addDependentSubTypes(type.def.value.flatMap(member => member.fields.map(field => field.type)).filter(type => typeof type === "number"));
1486
176
  break;
1487
177
  default:
1488
178
  {
1489
179
  // force compilation error if any types don't have a case
1490
- const exhaustiveCheck = type;
1491
- log.error(`Unhandled TyMV14 type ${exhaustiveCheck}`);
180
+ const exhaustiveCheck = type.def;
181
+ log.error(`Unhandled V15Type type ${exhaustiveCheck}`);
1492
182
  }
1493
183
  }
1494
184
  }
1495
185
  };
1496
-
1497
- /**
1498
- * This module is largely copied from https://github.com/0xKheops/substrate-metadata-explorer/blob/4b5a991e5ced45cad3b8675ff9104b8366d20429/packages/sme-codegen/src/types/getConstantVariableName.ts
1499
- *
1500
- * The primary difference between this module and `sme-codegen` is in the output.
1501
- *
1502
- * The `sme-codegen` module exports typescript code as a string, which can then be interpretted in order to construct subshape objects.
1503
- *
1504
- * Whereas this module directly exports the subshape objects described by that code.
1505
- */
1506
-
1507
- /** Returns a unique name (relative to all of the types in `metadata`) to identify this type. */
1508
- const getTypeName = (metadata, type) => {
1509
- const uniqueName = getUniqueTypeName(metadata, type);
1510
- return `${uniqueName.charAt(0).toUpperCase()}${uniqueName.substring(1)}`;
186
+ const remapTypeIds = (metadata, getNewTypeId) => {
187
+ remapLookupTypeIds(metadata, getNewTypeId);
188
+ remapStorageTypeIds(metadata, getNewTypeId);
189
+ remapRuntimeApisTypeIds(metadata, getNewTypeId);
1511
190
  };
1512
-
1513
- /**
1514
- * Tries each of `getSimpleTypeName`, `getSmartTypeName`, `getFullTypeName` in order and
1515
- * returns the first name which is unique in the collection of types in `metadata`.
1516
- */
1517
- const getUniqueTypeName = (metadata, type) => {
1518
- const rawTypeName = getRawTypeName(type);
1519
- if (type.path.length < 1) return rawTypeName;
1520
-
1521
- // use simpleName if it is unique
1522
- const simpleName = getSimpleTypeName(type);
1523
- if (!metadata.tys.some(t => t.id !== type.id && getSimpleTypeName(t) === simpleName)) return simpleName;
1524
-
1525
- // use smartName if it is unique
1526
- const smartName = getSmartTypeName(type);
1527
- if (!metadata.tys.some(t => t.id !== type.id && getSmartTypeName(t) === smartName)) return smartName;
1528
-
1529
- // use fullName if it is unique
1530
- const fullName = getFullTypeName(type);
1531
- if (!metadata.tys.some(t => t.id !== type.id && getFullTypeName(t) === fullName))
1532
- // return if fullName is unique
1533
- return fullName;
1534
-
1535
- // use fullName + type number
1536
- return `${fullName}${type.id}`;
191
+ const remapLookupTypeIds = (metadata, getNewTypeId) => {
192
+ for (const type of metadata.lookup) {
193
+ type.id = getNewTypeId(type.id);
194
+ for (const param of type.params) {
195
+ if (typeof param.type !== "number") continue;
196
+ param.type = getNewTypeId(param.type);
197
+ }
198
+ switch (type.def.tag) {
199
+ case "array":
200
+ type.def.value.type = getNewTypeId(type.def.value.type);
201
+ break;
202
+ case "bitSequence":
203
+ type.def.value.bitOrderType = getNewTypeId(type.def.value.bitOrderType);
204
+ type.def.value.bitStoreType = getNewTypeId(type.def.value.bitStoreType);
205
+ break;
206
+ case "compact":
207
+ type.def.value = getNewTypeId(type.def.value);
208
+ break;
209
+ case "composite":
210
+ for (const field of type.def.value) {
211
+ if (typeof field.type !== "number") continue;
212
+ field.type = getNewTypeId(field.type);
213
+ }
214
+ break;
215
+ case "primitive":
216
+ break;
217
+ case "sequence":
218
+ type.def.value = getNewTypeId(type.def.value);
219
+ break;
220
+ case "tuple":
221
+ type.def.value = type.def.value.map(type => {
222
+ if (typeof type !== "number") return type;
223
+ return getNewTypeId(type);
224
+ });
225
+ break;
226
+ case "variant":
227
+ for (const member of type.def.value) {
228
+ for (const field of member.fields) {
229
+ if (typeof field.type !== "number") continue;
230
+ field.type = getNewTypeId(field.type);
231
+ }
232
+ }
233
+ break;
234
+ default:
235
+ {
236
+ // force compilation error if any types don't have a case
237
+ const exhaustiveCheck = type.def;
238
+ log.error(`Unhandled V15Type type ${exhaustiveCheck}`);
239
+ }
240
+ }
241
+ }
242
+ };
243
+ const remapStorageTypeIds = (metadata, getNewTypeId) => {
244
+ for (const pallet of metadata.pallets) {
245
+ for (const item of pallet.storage?.items ?? []) {
246
+ if (item.type.tag === "plain") item.type.value = getNewTypeId(item.type.value);
247
+ if (item.type.tag === "map") {
248
+ item.type.value.key = getNewTypeId(item.type.value.key);
249
+ item.type.value.value = getNewTypeId(item.type.value.value);
250
+ }
251
+ }
252
+ for (const constant of pallet.constants ?? []) {
253
+ constant.type = getNewTypeId(constant.type);
254
+ }
255
+ }
256
+ };
257
+ const remapRuntimeApisTypeIds = (metadata, getNewTypeId) => {
258
+ for (const runtimeApi of metadata.apis) {
259
+ for (const method of runtimeApi.methods ?? []) {
260
+ for (const input of method.inputs) {
261
+ input.type = getNewTypeId(input.type);
262
+ }
263
+ method.output = getNewTypeId(method.output);
264
+ }
265
+ }
1537
266
  };
1538
-
1539
- /** Gets "Type" + type number */
1540
- const getRawTypeName = type => `Type${type.id}`;
1541
-
1542
- /** Gets the last element of `type.path` */
1543
- const getSimpleTypeName = type => type.path.slice(-1)[0];
1544
-
1545
- /** Gets the first two elements, and the last element, of `type.path` and joins them together with `::` */
1546
- const getSmartTypeName = type => type.path.length > 3 ? normalizeTypeName([...type.path.slice(0, 2), ...type.path.slice(-1)].join("::")) : getFullTypeName(type);
1547
-
1548
- /** Gets all elements of `type.path` and joins them together with `::` */
1549
- const getFullTypeName = type => normalizeTypeName(type.path.join("::"));
1550
267
 
1551
268
  /**
1552
- * This module is largely copied from https://github.com/0xKheops/substrate-metadata-explorer/blob/4b5a991e5ced45cad3b8675ff9104b8366d20429/packages/sme-codegen/src/types/getShape.ts
269
+ * Extracts the `version` u8 from a SCALE-encoded metadata blob and returns it as a `number`.
1553
270
  *
1554
- * The primary difference between this module and `sme-codegen` is in the output.
1555
- *
1556
- * The `sme-codegen` module exports typescript code as a string, which can then be interpretted in order to construct subshape objects.
1557
- *
1558
- * Whereas this module directly exports the subshape objects described by that code.
271
+ * Only reads the first 40 bytes of the blob.
1559
272
  */
1560
- const getShape = (metadata, typeId, gotShapes = new Map()) => {
1561
- const type = metadata.tys.find(type => type.id === typeId);
1562
- if (!type) throw new Error(`Type not found (${typeId})`);
1563
-
1564
- // Short circuit if we've already encountered this shape
1565
- const typeName = getTypeName(metadata, type);
1566
- if (gotShapes.has(typeName)) return gotShapes.get(typeName);
1567
-
1568
- // TODO: Use `$.deferred(() => Type)` for self-referential types
1569
-
1570
- // Get shape, add to gotShapes list, return shape
1571
- const shape = getTypeShape(metadata, type, gotShapes);
1572
- gotShapes.set(typeName, shape);
1573
- return shape;
1574
- };
1575
- const getTypeShape = (metadata, type, gotShapes) => {
1576
- const tyType = type.type;
1577
- switch (tyType) {
1578
- case "Primitive":
1579
- return getPrimitiveShape(type);
1580
- case "SizedArray":
1581
- return getSizedArrayShape(metadata, type, gotShapes);
1582
- case "Compact":
1583
- return getCompactShape(metadata, type, gotShapes);
1584
- case "Sequence":
1585
- return getSequenceShape(metadata, type, gotShapes);
1586
- case "Struct":
1587
- return getStructShape(metadata, type, gotShapes);
1588
- case "Tuple":
1589
- return getTupleShape(metadata, type, gotShapes);
1590
- case "Union":
1591
- return getUnionShape(metadata, type, gotShapes);
1592
- case "BitSequence":
1593
- return $.bitSequence;
1594
- default:
1595
- {
1596
- // force compilation error if any types don't have a case
1597
- const exhaustiveCheck = tyType;
1598
- throw new Error(`Unsupported type shape ${exhaustiveCheck}`);
1599
- }
273
+ const getMetadataVersion = metadataRpc => {
274
+ try {
275
+ return Struct({
276
+ magicNumber: u32,
277
+ version: u8
278
+ }).dec(metadataRpc).version;
279
+ } catch {
280
+ return 0;
1600
281
  }
1601
282
  };
1602
- const tyIsU8 = type => type?.type === "Primitive" && type.kind === "u8";
1603
- const getPrimitiveShape = primitive => {
1604
- // TODO: Test that `char` and `$.u8` are equivalent (`$.char` does not exist)
1605
- if (primitive.kind === "char") return $.u8;
1606
- return $[primitive.kind];
1607
- };
1608
- const getSizedArrayShape = (metadata, sizedArray, gotShapes) => {
1609
- // Get the type definition for the items of this array from the metadata
1610
- const typeParam = metadata.tys.find(({
1611
- id
1612
- }) => id === sizedArray.typeParam);
1613
- if (!typeParam) {
1614
- const typeName = getTypeName(metadata, sizedArray);
1615
- throw new Error(`Could not find typeParam ${sizedArray.typeParam} for sizedArray ${typeName}`);
1616
- }
1617
283
 
1618
- // Shortcut for uint8 arrays
1619
- if (tyIsU8(typeParam)) return $.sizedUint8Array(sizedArray.len);
1620
-
1621
- // Get the subshape object for the items of this array
1622
- const typeParamShape = getShape(metadata, typeParam.id, gotShapes);
1623
-
1624
- // Return a subshape sizedArray
1625
- return $.sizedArray(typeParamShape, sizedArray.len);
284
+ const decodeMetadata = metadataRpc => {
285
+ const metadataVersion = getMetadataVersion(metadataRpc);
286
+ if (metadataVersion !== 15 && metadataVersion !== 14) return {
287
+ metadataVersion
288
+ };
289
+ const decoded = metadata.dec(metadataRpc);
290
+ if (decoded.metadata.tag === "v15") return {
291
+ metadataVersion,
292
+ metadata: decoded.metadata.value,
293
+ tag: decoded.metadata.tag
294
+ };
295
+ if (decoded.metadata.tag === "v14") return {
296
+ metadataVersion,
297
+ metadata: decoded.metadata.value,
298
+ tag: decoded.metadata.tag
299
+ };
300
+ return {
301
+ metadataVersion
302
+ };
1626
303
  };
1627
- const getCompactShape = (metadata, compact, gotShapes) => {
1628
- // Get the type definition for the item of this compact from the metadata
1629
- const typeParam = metadata.tys.find(({
1630
- id
1631
- }) => id === compact.typeParam);
1632
- if (!typeParam) {
1633
- const typeName = getTypeName(metadata, compact);
1634
- throw new Error(`Could not find typeParam ${compact.typeParam} for compact ${typeName}`);
1635
- }
1636
304
 
1637
- // Get the subshape object for the item of this compact
1638
- const typeParamShape = getShape(metadata, typeParam.id, gotShapes);
1639
-
1640
- // Return a subshape compact
1641
- return $.compact(typeParamShape);
1642
- };
1643
- const getSequenceShape = (metadata, sequence, gotShapes) => {
1644
- // Get the type definition for the items of this sequence from the metadata
1645
- const typeParam = metadata.tys.find(({
1646
- id
1647
- }) => id === sequence.typeParam);
1648
- if (!typeParam) {
1649
- const typeName = getTypeName(metadata, sequence);
1650
- throw new Error(`Could not find typeParam ${sequence.typeParam} for sequence ${typeName}`);
305
+ const decodeScale = (scaleCoder, change, error) => {
306
+ if (change === null) return null;
307
+ try {
308
+ return scaleCoder?.value?.dec(change) ?? null;
309
+ } catch (cause) {
310
+ log.warn(error ?? `Failed to decode ${change}`, cause);
311
+ return null;
1651
312
  }
1652
-
1653
- // Shortcut for uint8 sequences
1654
- if (tyIsU8(typeParam)) return $.uint8Array;
1655
-
1656
- // Get the subshape object for the items of this sequence
1657
- const typeParamShape = getShape(metadata, typeParam.id, gotShapes);
1658
-
1659
- // Return a subshape sequence
1660
- return $.array(typeParamShape);
1661
313
  };
1662
- const getStructShape = (metadata, struct, gotShapes) => {
1663
- // If there's only one field and it has no name, don't wrap it in $.object
1664
- if (struct.fields.length === 1 && !struct.fields[0].name) return getShape(metadata, struct.fields[0].ty, gotShapes);
1665
314
 
1666
- // Check that all fields have a name
1667
- if (!struct.fields.every(field => field.name)) {
1668
- const typeName = getTypeName(metadata, struct);
1669
- throw new Error(`Could not build subshape object for struct ${struct.id} (${typeName})): Not all fields have a name`);
315
+ const encodeMetadata = ({
316
+ metadata: metadata$1,
317
+ tag
318
+ }) => toHex(metadata.enc({
319
+ magicNumber,
320
+ metadata: tag === "v15" ? {
321
+ tag,
322
+ value: metadata$1
323
+ } : {
324
+ tag,
325
+ value: metadata$1
326
+ }
327
+ }));
328
+
329
+ const encodeStateKey = (scaleCoder, error, ...args) => {
330
+ try {
331
+ return scaleCoder?.keys?.enc(...args);
332
+ } catch (cause) {
333
+ log.warn(error ?? `Failed to encode stateKey ${JSON.stringify(args)}`, cause);
334
+ return;
1670
335
  }
1671
-
1672
- // Get the type definition for the fields of this struct from the metadata
1673
- const fieldsShape = struct.fields.map(field => $.field(normalizeIdent(field.name), getShape(metadata, field.ty, gotShapes)));
1674
- return $.object(...fieldsShape);
1675
336
  };
1676
- const getTupleShape = (metadata, tuple, gotShapes) =>
1677
- // Get the type definition for the fields of this tuple from the metadata and wrap them in `$.tuple`
1678
- $.tuple(...tuple.fields.map(type => getShape(metadata, type, gotShapes)));
1679
- const getUnionShape = (metadata, union, gotShapes) => {
1680
- if (union.members.every(member => !member.fields.length)) return $.literalUnion(Object.fromEntries(union.members.map(member => [member.index, normalizeIdent(member.name)])));
1681
-
1682
- // TODO: Check if invalid
1683
- if (union.members.length === 2 && union.path[union.path.length - 1] === "Option" && union.members[0]?.name === "None" && union.members[1]?.name === "Some") return $.option(getShape(metadata, union.members[1].fields[0].ty, gotShapes));
1684
- return $.taggedUnion("type", Object.fromEntries(union.members.map(member => {
1685
- const args = [];
1686
337
 
1687
- // invalid if only some fields (but not all of them) have a name
1688
- if (member.fields.some(field => field.name) && !member.fields.every(field => field.name)) {
1689
- const typeName = getTypeName(metadata, union);
1690
- throw new Error(`Could not build subshape object for union ${union.id} (${typeName}): Not all fields have a name`);
1691
- }
1692
- if (member.fields.every(field => field.name)) for (const field of member.fields) args.push($.field(normalizeIdent(field.name), getShape(metadata, field.ty, gotShapes)));else if (member.fields.length > 1) args.push($.field("value", $.tuple(...member.fields.map(field => getShape(metadata, field.ty, gotShapes)))));else args.push($.field("value", getShape(metadata, member.fields[0].ty, gotShapes)));
1693
- return [member.index, $.variant(normalizeIdent(member.name), ...args)];
1694
- })));
338
+ /**
339
+ * For the substrate-tokens (and other) modules, we configure the `onChainId` field in chaindata to tell the module how to query each token.
340
+ * These queries are made to the tokens pallet.
341
+ * E.g. api.query.Tokens.Account(accountAddress, papiParse(onChainId))
342
+ *
343
+ * The `onChainId` field on chaindata must be a JSON-parseable string, but for some SCALE types (especially the Binary type) we must
344
+ * use specific `polkadot-api` classes to handle SCALE-encoding the statekey.
345
+ *
346
+ * Some examples:
347
+ * Input: `5`
348
+ * Output: `5`
349
+ *
350
+ * Input: `{ type: "DexShare", value: [ { type: "Token", value: { type: "ACA" } }, { type: "Token", value: { type: "AUSD" } } ] }`
351
+ * Output: `Enum("DexShare", [Enum("Token", Enum("ACA")), Enum("Token", Enum("AUSD"))])`
352
+ *
353
+ * Input: `{ type: "LiquidCrowdloan", value: 13 }`
354
+ * Output: `Enum("LiquidCrowdloan", 13)`
355
+ *
356
+ * Input: `{ type: "NativeToken", value: "bigint:2" }`
357
+ * Output: `Enum("NativeToken", 2n)`
358
+ *
359
+ * Input: `{ type: "Erc20", value: "hex:0x07df96d1341a7d16ba1ad431e2c847d978bc2bce" }`
360
+ * Output: `Enum("Erc20", Binary.fromHex("0x07df96d1341a7d16ba1ad431e2c847d978bc2bce"))`
361
+ *
362
+ * Input: `{ type: "Stellar", value: { code: "bin:TZS", issuer: "hex:0x34c94b2a4ba9e8b57b22547dcbb30f443c4cb02da3829a89aa1bd4780e4466ba" } }`
363
+ * Output: `Enum("Stellar", { code: Binary.fromText("TZS"), issuer: Binary.fromHex("0x34c94b2a4ba9e8b57b22547dcbb30f443c4cb02da3829a89aa1bd4780e4466ba") })`
364
+ */
365
+ const papiParse = text => {
366
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
367
+ const reviver = (_key, value) => {
368
+ if (typeof value !== "string") return value;
369
+ if (value.startsWith("bigint:")) return BigInt(value.slice("bigint:".length));
370
+ if (value.startsWith("hex:")) return Binary.fromHex(value.slice("hex:".length));
371
+ if (value.startsWith("bin:")) return Binary.fromText(value.slice("bin:".length));
372
+ return value;
373
+ };
374
+ if (typeof text !== "string") return text;
375
+ return JSON.parse(text, reviver);
376
+ };
377
+ const papiStringify = (value, space) => {
378
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
379
+ const replacer = (_key, value) => {
380
+ if (typeof value === "bigint") return `bigint:${String(value)}`;
381
+ if (value instanceof Binary) return `hex:${value.asHex()}`;
382
+ return value;
383
+ };
384
+ return JSON.stringify(value, replacer, space);
1695
385
  };
1696
386
 
1697
- // TODO: Get the DX of this lib as close as possible to the DX of `const jsonResult = '{"someKey":"someValue"}'; JSON.decode(jsonResult)`
1698
- suppressPortableRegistryConsoleWarnings();
1699
-
1700
- export { $emptyKey, $era, $extrinsic, $field, $hash, $metadataV14, $null, $partialEmptyKey, $partialMultiKey, $partialSingleKey, $primitiveKind, $storageKey, $ty, $tyDef, $tyId, Blake2Hasher, DecodeNonTransparentKeyError, Era, Hasher, IdentityHasher, SignerError, TwoxHasher, addDependentTypes, blake2_128, blake2_128Concat, blake2_256, blake2_512, blake2_64, decodeMetadata, filterMetadataPalletsAndItems, getFullTypeName, getMetadataVersion, getOrInit, getRawTypeName, getShape, getSimpleTypeName, getSmartTypeName, getTypeName, getTypeShape, getUniqueTypeName, identity, normalizeDocs, normalizeIdent, normalizePackageName, normalizeTypeName, normalizeVariableName, ss58, stringifyKey, stringifyPropertyAccess, transformMetadata as transformMetadataV14, transformTys, twox128, twox256, twox64, twox64Concat, watCryptoWaitReady };
387
+ export { compactMetadata, decodeMetadata, decodeScale, encodeMetadata, encodeStateKey, getMetadataVersion, magicNumber, papiParse, papiStringify };