@polkadot-api/ws-middleware 1.0.0-canary.3789023

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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/esm/index.mjs +12 -0
  4. package/dist/esm/index.mjs.map +1 -0
  5. package/dist/esm/legacy/downstream/archive.mjs +96 -0
  6. package/dist/esm/legacy/downstream/archive.mjs.map +1 -0
  7. package/dist/esm/legacy/downstream/chain-head.mjs +214 -0
  8. package/dist/esm/legacy/downstream/chain-head.mjs.map +1 -0
  9. package/dist/esm/legacy/downstream/chainspec.mjs +18 -0
  10. package/dist/esm/legacy/downstream/chainspec.mjs.map +1 -0
  11. package/dist/esm/legacy/downstream/downstream.mjs +107 -0
  12. package/dist/esm/legacy/downstream/downstream.mjs.map +1 -0
  13. package/dist/esm/legacy/downstream/storage.mjs +57 -0
  14. package/dist/esm/legacy/downstream/storage.mjs.map +1 -0
  15. package/dist/esm/legacy/downstream/transaction.mjs +48 -0
  16. package/dist/esm/legacy/downstream/transaction.mjs.map +1 -0
  17. package/dist/esm/legacy/upstream/blocks/blocks.mjs +309 -0
  18. package/dist/esm/legacy/upstream/blocks/blocks.mjs.map +1 -0
  19. package/dist/esm/legacy/upstream/blocks/index.mjs +7 -0
  20. package/dist/esm/legacy/upstream/blocks/index.mjs.map +1 -0
  21. package/dist/esm/legacy/upstream/blocks/upstream-events.mjs +92 -0
  22. package/dist/esm/legacy/upstream/blocks/upstream-events.mjs.map +1 -0
  23. package/dist/esm/legacy/upstream/proofs.mjs +41 -0
  24. package/dist/esm/legacy/upstream/proofs.mjs.map +1 -0
  25. package/dist/esm/legacy/upstream/upstream.mjs +108 -0
  26. package/dist/esm/legacy/upstream/upstream.mjs.map +1 -0
  27. package/dist/esm/legacy/utils/create-opaque-token.mjs +7 -0
  28. package/dist/esm/legacy/utils/create-opaque-token.mjs.map +1 -0
  29. package/dist/esm/legacy/utils/fromShittyHeader.mjs +31 -0
  30. package/dist/esm/legacy/utils/fromShittyHeader.mjs.map +1 -0
  31. package/dist/esm/legacy/utils/get-hasher-from-block.mjs +12 -0
  32. package/dist/esm/legacy/utils/get-hasher-from-block.mjs.map +1 -0
  33. package/dist/esm/legacy/utils/message-from-error.mjs +8 -0
  34. package/dist/esm/legacy/utils/message-from-error.mjs.map +1 -0
  35. package/dist/esm/legacy/utils/share-latest.mjs +9 -0
  36. package/dist/esm/legacy/utils/share-latest.mjs.map +1 -0
  37. package/dist/esm/legacy/utils/with-latest-from-bp.mjs +40 -0
  38. package/dist/esm/legacy/utils/with-latest-from-bp.mjs.map +1 -0
  39. package/dist/esm/methods-router.mjs +41 -0
  40. package/dist/esm/methods-router.mjs.map +1 -0
  41. package/dist/esm/methods.mjs +40 -0
  42. package/dist/esm/methods.mjs.map +1 -0
  43. package/dist/esm/middleware.mjs +22 -0
  44. package/dist/esm/middleware.mjs.map +1 -0
  45. package/dist/esm/modern/fix-follow.mjs +79 -0
  46. package/dist/esm/modern/fix-follow.mjs.map +1 -0
  47. package/dist/esm/modern/fix-premature-blocks.mjs +94 -0
  48. package/dist/esm/modern/fix-premature-blocks.mjs.map +1 -0
  49. package/dist/esm/modern/fix-unordered-blocks.mjs +100 -0
  50. package/dist/esm/modern/fix-unordered-blocks.mjs.map +1 -0
  51. package/dist/esm/modern/fix-unordered-events.mjs +101 -0
  52. package/dist/esm/modern/fix-unordered-events.mjs.map +1 -0
  53. package/dist/esm/modern/modern.mjs +19 -0
  54. package/dist/esm/modern/modern.mjs.map +1 -0
  55. package/dist/esm/modern/patch-chainhead-events.mjs +16 -0
  56. package/dist/esm/modern/patch-chainhead-events.mjs.map +1 -0
  57. package/dist/esm/modern/unpin-hash.mjs +22 -0
  58. package/dist/esm/modern/unpin-hash.mjs.map +1 -0
  59. package/dist/esm/numeric-ids.mjs +37 -0
  60. package/dist/esm/numeric-ids.mjs.map +1 -0
  61. package/dist/esm/utils/get-async-middleware.mjs +60 -0
  62. package/dist/esm/utils/get-async-middleware.mjs.map +1 -0
  63. package/dist/esm/utils/utils.mjs +11 -0
  64. package/dist/esm/utils/utils.mjs.map +1 -0
  65. package/dist/index.d.ts +27 -0
  66. package/dist/index.js +1706 -0
  67. package/dist/index.js.map +1 -0
  68. package/package.json +57 -0
@@ -0,0 +1,108 @@
1
+ import { toHex, fromHex } from '@polkadot-api/utils';
2
+ import { Observable, map, mergeMap, EMPTY, merge, of, catchError } from 'rxjs';
3
+ import { getBlocks$ } from './blocks/index.mjs';
4
+ import { withLatestFromBp } from '../utils/with-latest-from-bp.mjs';
5
+ import { createClosestDescendantMerkleValue } from './proofs.mjs';
6
+
7
+ const createUpstream = (request) => {
8
+ const simpleRequest = (method, params, onSuccess, onError) => request(method, params, { onSuccess, onError });
9
+ const obsRequest = (method, params) => new Observable(
10
+ (observer) => simpleRequest(
11
+ method,
12
+ params,
13
+ (v) => {
14
+ observer.next(v);
15
+ observer.complete();
16
+ },
17
+ (e) => {
18
+ observer.error(e);
19
+ }
20
+ )
21
+ );
22
+ const {
23
+ upstream: getBlocks,
24
+ finalized$,
25
+ getHeader$,
26
+ hasher$,
27
+ clean
28
+ } = getBlocks$(request, obsRequest);
29
+ const runtimeCall = (atBlock, method, data) => obsRequest("state_call", [
30
+ method,
31
+ data,
32
+ atBlock
33
+ ]);
34
+ const stgDescendantValues = (at, rootKey) => {
35
+ const PAGE_SIZE = 1e3;
36
+ const getKeys = (startAtKey) => {
37
+ return obsRequest(
38
+ "state_getKeysPaged",
39
+ [rootKey, PAGE_SIZE, startAtKey || void 0, at]
40
+ ).pipe(
41
+ mergeMap((receivedKeys) => {
42
+ const keys = receivedKeys[0] === startAtKey ? receivedKeys.slice(1) : receivedKeys;
43
+ const continuation = receivedKeys.length < PAGE_SIZE ? EMPTY : getKeys(receivedKeys.at(-1));
44
+ return merge(of(keys), continuation);
45
+ })
46
+ );
47
+ };
48
+ const getValues = (keys, nSplits = 0) => keys.length ? obsRequest("state_queryStorageAt", [keys, at]).pipe(
49
+ map(([{ changes }]) => changes),
50
+ catchError((e) => {
51
+ if (nSplits > 3) throw e;
52
+ const midIdx = Math.floor(keys.length / 2);
53
+ return merge(
54
+ getValues(keys.slice(0, midIdx), ++nSplits),
55
+ getValues(keys.slice(midIdx), nSplits)
56
+ );
57
+ })
58
+ ) : EMPTY;
59
+ return getKeys().pipe(mergeMap((keys) => getValues(keys)));
60
+ };
61
+ const stgDescendantHashes = (at, rootKey) => stgDescendantValues(at, rootKey).pipe(
62
+ withLatestFromBp(hasher$),
63
+ map(
64
+ ([hasher, results]) => results.map(
65
+ ([key, value]) => [key, toHex(hasher(fromHex(value)))]
66
+ )
67
+ )
68
+ );
69
+ const stgClosestDescendant = createClosestDescendantMerkleValue(obsRequest);
70
+ const [stgValue, stgHash] = ["state_getStorage", "state_getStorageHash"].map(
71
+ (method) => (atBlock, key) => obsRequest(method, [
72
+ key,
73
+ atBlock
74
+ ])
75
+ );
76
+ const methods = obsRequest("rpc_methods", []);
77
+ const chainName = obsRequest("system_name", []);
78
+ const properties = obsRequest("system_properties", []);
79
+ const getBody = (at) => obsRequest(
80
+ "chain_getBlock",
81
+ [at]
82
+ );
83
+ const getBlockHash$ = (height) => obsRequest("chain_getBlockHash", [height]);
84
+ const genesisHash = getBlockHash$(0);
85
+ return {
86
+ getBlocks,
87
+ finalized$,
88
+ getBlockHash$,
89
+ getHeader$,
90
+ stgValue,
91
+ stgHash,
92
+ stgDescendantValues,
93
+ stgDescendantHashes,
94
+ stgClosestDescendant,
95
+ runtimeCall,
96
+ getBody,
97
+ chainName,
98
+ properties,
99
+ genesisHash,
100
+ clean,
101
+ methods,
102
+ request: simpleRequest,
103
+ obsRequest
104
+ };
105
+ };
106
+
107
+ export { createUpstream };
108
+ //# sourceMappingURL=upstream.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream.mjs","sources":["../../../../src/legacy/upstream/upstream.ts"],"sourcesContent":["import { ClientRequest } from \"@polkadot-api/raw-client\"\nimport { fromHex, toHex } from \"@polkadot-api/utils\"\nimport { catchError, EMPTY, map, merge, mergeMap, Observable, of } from \"rxjs\"\nimport { getBlocks$ } from \"./blocks\"\nimport { withLatestFromBp } from \"../utils/with-latest-from-bp\"\nimport { createClosestDescendantMerkleValue } from \"./proofs\"\n\nexport const createUpstream = (request: ClientRequest<any, any>) => {\n const simpleRequest = <Args extends Array<any>, Payload>(\n method: string,\n params: Args,\n onSuccess: (value: Payload) => void,\n onError: (e: any) => void,\n ): (() => void) => request(method, params, { onSuccess, onError })\n\n const obsRequest = <Args extends Array<any>, Payload>(\n method: string,\n params: Args,\n ): Observable<Payload> =>\n new Observable((observer) =>\n simpleRequest<Args, Payload>(\n method,\n params,\n (v) => {\n observer.next(v)\n observer.complete()\n },\n (e) => {\n observer.error(e)\n },\n ),\n )\n\n const {\n upstream: getBlocks,\n finalized$,\n getHeader$,\n hasher$,\n clean,\n } = getBlocks$(request, obsRequest)\n\n const runtimeCall = (atBlock: string, method: string, data: string) =>\n obsRequest<[string, string, string], string | null>(\"state_call\", [\n method,\n data,\n atBlock,\n ])\n\n const stgDescendantValues = (\n at: string,\n rootKey: string,\n ): Observable<Array<[string, string]>> => {\n const PAGE_SIZE = 1000\n const getKeys = (startAtKey?: string): Observable<string[]> => {\n return obsRequest<[string, number, string | undefined, string], string[]>(\n \"state_getKeysPaged\",\n [rootKey, PAGE_SIZE, startAtKey || undefined, at],\n ).pipe(\n mergeMap((receivedKeys) => {\n const keys =\n receivedKeys[0] === startAtKey\n ? receivedKeys.slice(1)\n : receivedKeys\n\n const continuation =\n receivedKeys.length < PAGE_SIZE\n ? EMPTY\n : getKeys(receivedKeys.at(-1))\n\n return merge(of(keys), continuation)\n }),\n )\n }\n\n const getValues = (\n keys: string[],\n nSplits = 0,\n ): Observable<Array<[string, string]>> =>\n keys.length\n ? obsRequest<\n [string[], string],\n [{ block: string; changes: Array<[string, string]> }]\n >(\"state_queryStorageAt\", [keys, at]).pipe(\n map(([{ changes }]) => changes),\n catchError((e: any) => {\n if (nSplits > 3) throw e\n\n const midIdx = Math.floor(keys.length / 2)\n return merge(\n getValues(keys.slice(0, midIdx), ++nSplits),\n getValues(keys.slice(midIdx), nSplits),\n )\n }),\n )\n : EMPTY\n\n return getKeys().pipe(mergeMap((keys) => getValues(keys)))\n }\n\n const stgDescendantHashes = (at: string, rootKey: string) =>\n stgDescendantValues(at, rootKey).pipe(\n withLatestFromBp(hasher$),\n map(([hasher, results]) =>\n results.map(\n ([key, value]) =>\n [key, toHex(hasher(fromHex(value)))] as [string, string],\n ),\n ),\n )\n\n const stgClosestDescendant = createClosestDescendantMerkleValue(obsRequest)\n\n const [stgValue, stgHash] = [\"state_getStorage\", \"state_getStorageHash\"].map(\n (method) => (atBlock: string, key: string) =>\n obsRequest<[string, string | undefined], string | null>(method, [\n key,\n atBlock,\n ]),\n )\n\n const methods = obsRequest<[], { methods: string[] }>(\"rpc_methods\", [])\n const chainName = obsRequest<[], string>(\"system_name\", [])\n const properties = obsRequest<[], {}>(\"system_properties\", [])\n const getBody = (at: string) =>\n obsRequest<[string], { block: { extrinsics: Array<string> } }>(\n \"chain_getBlock\",\n [at],\n )\n\n const getBlockHash$ = (height: number) =>\n obsRequest<[height: number], string>(\"chain_getBlockHash\", [height])\n const genesisHash = getBlockHash$(0)\n\n return {\n getBlocks,\n finalized$,\n getBlockHash$,\n getHeader$,\n stgValue,\n stgHash,\n stgDescendantValues,\n stgDescendantHashes,\n stgClosestDescendant,\n runtimeCall,\n getBody,\n chainName,\n properties,\n genesisHash,\n clean,\n methods,\n request: simpleRequest,\n obsRequest,\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ let latestId = 1;
2
+ const createOpaqueToken = () => {
3
+ return `${latestId++}${Date.now()}`;
4
+ };
5
+
6
+ export { createOpaqueToken };
7
+ //# sourceMappingURL=create-opaque-token.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-opaque-token.mjs","sources":["../../../../src/legacy/utils/create-opaque-token.ts"],"sourcesContent":["let latestId = 1\nexport const createOpaqueToken = (): string => {\n // TODO: make this fancier\n return `${latestId++}${Date.now()}`\n}\n"],"names":[],"mappings":"AAAA,IAAI,QAAA,GAAW,CAAA;AACR,MAAM,oBAAoB,MAAc;AAE7C,EAAA,OAAO,CAAA,EAAG,QAAA,EAAU,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,CAAA;AACnC;;;;"}
@@ -0,0 +1,31 @@
1
+ import { compact } from '@polkadot-api/substrate-bindings';
2
+ import { fromHex, mergeUint8, toHex } from '@polkadot-api/utils';
3
+
4
+ const getFromShittyHeader = (hasher) => ({
5
+ parentHash,
6
+ number: rawNumber,
7
+ stateRoot,
8
+ extrinsicsRoot,
9
+ digest
10
+ }) => {
11
+ const number = Number(rawNumber);
12
+ const rawDigests = digest.logs.map(fromHex);
13
+ const rawHeader = mergeUint8([
14
+ fromHex(parentHash),
15
+ compact.enc(number),
16
+ fromHex(stateRoot),
17
+ fromHex(extrinsicsRoot),
18
+ compact.enc(digest.logs.length),
19
+ ...rawDigests
20
+ ]);
21
+ return {
22
+ parent: parentHash,
23
+ hash: toHex(hasher(rawHeader)),
24
+ number,
25
+ hasUpgrade: rawDigests.some(([x]) => x === 8),
26
+ header: toHex(rawHeader)
27
+ };
28
+ };
29
+
30
+ export { getFromShittyHeader };
31
+ //# sourceMappingURL=fromShittyHeader.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fromShittyHeader.mjs","sources":["../../../../src/legacy/utils/fromShittyHeader.ts"],"sourcesContent":["import { compact } from \"@polkadot-api/substrate-bindings\"\nimport { fromHex, mergeUint8, toHex } from \"@polkadot-api/utils\"\nimport { ShittyHeader } from \"../types\"\n\nexport const getFromShittyHeader =\n (hasher: (input: Uint8Array) => Uint8Array) =>\n ({\n parentHash,\n number: rawNumber,\n stateRoot,\n extrinsicsRoot,\n digest,\n }: ShittyHeader) => {\n const number = Number(rawNumber)\n const rawDigests = digest.logs.map(fromHex)\n\n const rawHeader = mergeUint8([\n fromHex(parentHash),\n compact.enc(number),\n fromHex(stateRoot),\n fromHex(extrinsicsRoot),\n compact.enc(digest.logs.length),\n ...rawDigests,\n ])\n\n return {\n parent: parentHash,\n hash: toHex(hasher(rawHeader)),\n number,\n hasUpgrade: rawDigests.some(([x]) => x === 8),\n header: toHex(rawHeader),\n }\n }\n"],"names":[],"mappings":";;;AAIO,MAAM,mBAAA,GACX,CAAC,MAAA,KACD,CAAC;AAAA,EACC,UAAA;AAAA,EACA,MAAA,EAAQ,SAAA;AAAA,EACR,SAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,KAAoB;AAClB,EAAA,MAAM,MAAA,GAAS,OAAO,SAAS,CAAA;AAC/B,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AAE1C,EAAA,MAAM,YAAY,UAAA,CAAW;AAAA,IAC3B,QAAQ,UAAU,CAAA;AAAA,IAClB,OAAA,CAAQ,IAAI,MAAM,CAAA;AAAA,IAClB,QAAQ,SAAS,CAAA;AAAA,IACjB,QAAQ,cAAc,CAAA;AAAA,IACtB,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AAAA,IAC9B,GAAG;AAAA,GACJ,CAAA;AAED,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,UAAA;AAAA,IACR,IAAA,EAAM,KAAA,CAAM,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,IAC7B,MAAA;AAAA,IACA,UAAA,EAAY,WAAW,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA,KAAM,MAAM,CAAC,CAAA;AAAA,IAC5C,MAAA,EAAQ,MAAM,SAAS;AAAA,GACzB;AACF;;;;"}
@@ -0,0 +1,12 @@
1
+ import { Blake2256, Keccak256 } from '@polkadot-api/substrate-bindings';
2
+ import { getFromShittyHeader } from './fromShittyHeader.mjs';
3
+
4
+ const hashers = [Blake2256, Keccak256];
5
+ const fns = hashers.map(getFromShittyHeader);
6
+ const noHasher = (_) => {
7
+ throw new Error("Hasher not supported");
8
+ };
9
+ const getHasherFromBlock = (shitHeader) => (hash) => hashers[fns.findIndex((fn) => fn(shitHeader).hash === hash)] || noHasher;
10
+
11
+ export { getHasherFromBlock };
12
+ //# sourceMappingURL=get-hasher-from-block.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-hasher-from-block.mjs","sources":["../../../../src/legacy/utils/get-hasher-from-block.ts"],"sourcesContent":["import { Blake2256, Keccak256 } from \"@polkadot-api/substrate-bindings\"\nimport { getFromShittyHeader } from \"./fromShittyHeader\"\nimport { ShittyHeader } from \"../types\"\n\nconst hashers = [Blake2256, Keccak256]\nconst fns = hashers.map(getFromShittyHeader)\nconst noHasher = (_: Uint8Array): Uint8Array => {\n throw new Error(\"Hasher not supported\")\n}\n\nexport const getHasherFromBlock =\n (shitHeader: ShittyHeader) =>\n (hash: string): ((data: Uint8Array) => Uint8Array) =>\n hashers[fns.findIndex((fn) => fn(shitHeader).hash === hash)] || noHasher\n"],"names":[],"mappings":";;;AAIA,MAAM,OAAA,GAAU,CAAC,SAAA,EAAW,SAAS,CAAA;AACrC,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,mBAAmB,CAAA;AAC3C,MAAM,QAAA,GAAW,CAAC,CAAA,KAA8B;AAC9C,EAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AACxC,CAAA;AAEO,MAAM,qBACX,CAAC,UAAA,KACD,CAAC,IAAA,KACC,QAAQ,GAAA,CAAI,SAAA,CAAU,CAAC,EAAA,KAAO,GAAG,UAAU,CAAA,CAAE,IAAA,KAAS,IAAI,CAAC,CAAA,IAAK;;;;"}
@@ -0,0 +1,8 @@
1
+ const getMsgFromErr = (e) => {
2
+ if (e instanceof Error) return e.message;
3
+ if (typeof e === "string") return e;
4
+ return "Unhandled exception";
5
+ };
6
+
7
+ export { getMsgFromErr };
8
+ //# sourceMappingURL=message-from-error.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-from-error.mjs","sources":["../../../../src/legacy/utils/message-from-error.ts"],"sourcesContent":["export const getMsgFromErr = (e: any) => {\n if (e instanceof Error) return e.message\n if (typeof e === \"string\") return e\n return \"Unhandled exception\"\n}\n"],"names":[],"mappings":"AAAO,MAAM,aAAA,GAAgB,CAAC,CAAA,KAAW;AACvC,EAAA,IAAI,CAAA,YAAa,KAAA,EAAO,OAAO,CAAA,CAAE,OAAA;AACjC,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,CAAA;AAClC,EAAA,OAAO,qBAAA;AACT;;;;"}
@@ -0,0 +1,9 @@
1
+ import { shareReplay } from 'rxjs';
2
+
3
+ const shareLatest = shareReplay({
4
+ refCount: true,
5
+ bufferSize: 1
6
+ });
7
+
8
+ export { shareLatest };
9
+ //# sourceMappingURL=share-latest.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share-latest.mjs","sources":["../../../../src/legacy/utils/share-latest.ts"],"sourcesContent":["import { Observable, shareReplay } from \"rxjs\"\n\nexport const shareLatest: <T>(base: Observable<T>) => Observable<T> =\n shareReplay({\n refCount: true,\n bufferSize: 1,\n })\n"],"names":[],"mappings":";;AAEO,MAAM,cACX,WAAA,CAAY;AAAA,EACV,QAAA,EAAU,IAAA;AAAA,EACV,UAAA,EAAY;AACd,CAAC;;;;"}
@@ -0,0 +1,40 @@
1
+ import { Observable } from 'rxjs';
2
+
3
+ const withLatestFromBp = (latest$) => (base$) => new Observable((observer) => {
4
+ let latest;
5
+ let prev = [];
6
+ const subscription = base$.subscribe({
7
+ next(v) {
8
+ if (prev) prev.push(v);
9
+ else observer.next([latest, v]);
10
+ },
11
+ error(e) {
12
+ observer.error(e);
13
+ },
14
+ complete() {
15
+ observer.complete();
16
+ }
17
+ });
18
+ subscription.add(
19
+ latest$.subscribe({
20
+ next(v) {
21
+ latest = v;
22
+ if (prev) {
23
+ const copy = [...prev];
24
+ prev = null;
25
+ copy.forEach((p) => observer.next([latest, p]));
26
+ }
27
+ },
28
+ error(e) {
29
+ observer.error(e);
30
+ },
31
+ complete() {
32
+ if (prev) observer.error(new Error("Empty complete"));
33
+ }
34
+ })
35
+ );
36
+ return subscription;
37
+ });
38
+
39
+ export { withLatestFromBp };
40
+ //# sourceMappingURL=with-latest-from-bp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-latest-from-bp.mjs","sources":["../../../../src/legacy/utils/with-latest-from-bp.ts"],"sourcesContent":["import { Observable } from \"rxjs\"\n\nexport const withLatestFromBp =\n <T, S>(latest$: Observable<T>) =>\n (base$: Observable<S>) =>\n new Observable<[T, S]>((observer) => {\n let latest: T\n let prev: S[] | null = []\n\n const subscription = base$.subscribe({\n next(v) {\n if (prev) prev.push(v)\n else observer.next([latest, v])\n },\n error(e) {\n observer.error(e)\n },\n complete() {\n observer.complete()\n },\n })\n\n subscription.add(\n latest$.subscribe({\n next(v) {\n latest = v\n if (prev) {\n const copy = [...prev]\n prev = null\n copy.forEach((p) => observer.next([latest, p]))\n }\n },\n error(e) {\n observer.error(e)\n },\n complete() {\n if (prev) observer.error(new Error(\"Empty complete\"))\n },\n }),\n )\n\n return subscription\n })\n"],"names":[],"mappings":";;AAEO,MAAM,gBAAA,GACX,CAAO,OAAA,KACP,CAAC,UACC,IAAI,UAAA,CAAmB,CAAC,QAAA,KAAa;AACnC,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,OAAmB,EAAC;AAExB,EAAA,MAAM,YAAA,GAAe,MAAM,SAAA,CAAU;AAAA,IACnC,KAAK,CAAA,EAAG;AACN,MAAA,IAAI,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AAAA,WAChB,QAAA,CAAS,IAAA,CAAK,CAAC,MAAA,EAAQ,CAAC,CAAC,CAAA;AAAA,IAChC,CAAA;AAAA,IACA,MAAM,CAAA,EAAG;AACP,MAAA,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,IAClB,CAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,QAAA,CAAS,QAAA,EAAS;AAAA,IACpB;AAAA,GACD,CAAA;AAED,EAAA,YAAA,CAAa,GAAA;AAAA,IACX,QAAQ,SAAA,CAAU;AAAA,MAChB,KAAK,CAAA,EAAG;AACN,QAAA,MAAA,GAAS,CAAA;AACT,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAA,GAAO,CAAC,GAAG,IAAI,CAAA;AACrB,UAAA,IAAA,GAAO,IAAA;AACP,UAAA,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,KAAM,QAAA,CAAS,KAAK,CAAC,MAAA,EAAQ,CAAC,CAAC,CAAC,CAAA;AAAA,QAChD;AAAA,MACF,CAAA;AAAA,MACA,MAAM,CAAA,EAAG;AACP,QAAA,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,MAClB,CAAA;AAAA,MACA,QAAA,GAAW;AACT,QAAA,IAAI,MAAM,QAAA,CAAS,KAAA,CAAM,IAAI,KAAA,CAAM,gBAAgB,CAAC,CAAA;AAAA,MACtD;AAAA,KACD;AAAA,GACH;AAEA,EAAA,OAAO,YAAA;AACT,CAAC;;;;"}
@@ -0,0 +1,41 @@
1
+ import { apply, jsonObj } from './utils/utils.mjs';
2
+ import { noop } from '@polkadot-api/utils';
3
+ import { getAsyncMiddleware } from './utils/get-async-middleware.mjs';
4
+
5
+ const RPC_METHODS = "rpc_methods";
6
+ const withMethods = (methods) => (base) => (onMsg, onHalt) => {
7
+ const result = { methods };
8
+ const { send, disconnect } = base(onMsg, onHalt);
9
+ return {
10
+ disconnect,
11
+ send(msg) {
12
+ if (msg.id && msg.method === RPC_METHODS) {
13
+ onMsg(jsonObj({ id: msg.id, result }));
14
+ } else send(msg);
15
+ }
16
+ };
17
+ };
18
+ const methodsRouter = (getMiddleware) => getAsyncMiddleware((onReady, request) => {
19
+ let nTries = 0;
20
+ let stopRequest = noop;
21
+ const getMethods = () => {
22
+ nTries++;
23
+ stopRequest = request(RPC_METHODS, [], {
24
+ onSuccess: ({ methods }) => {
25
+ onReady(apply(withMethods(methods), getMiddleware(methods)));
26
+ },
27
+ onError: () => {
28
+ if (nTries > 3) onReady(null);
29
+ else {
30
+ const token = setTimeout(getMethods, 500);
31
+ stopRequest = () => clearTimeout(token);
32
+ }
33
+ }
34
+ });
35
+ };
36
+ getMethods();
37
+ return () => stopRequest();
38
+ });
39
+
40
+ export { methodsRouter };
41
+ //# sourceMappingURL=methods-router.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"methods-router.mjs","sources":["../../src/methods-router.ts"],"sourcesContent":["import { Middleware } from \"./types\"\nimport { apply, jsonObj } from \"./utils\"\nimport { noop } from \"@polkadot-api/utils\"\nimport { getAsyncMiddleware } from \"./utils/get-async-middleware\"\n\nconst RPC_METHODS = \"rpc_methods\"\nconst withMethods =\n (methods: string[]): Middleware =>\n (base) =>\n (onMsg, onHalt) => {\n const result = { methods }\n const { send, disconnect } = base(onMsg, onHalt)\n return {\n disconnect,\n send(msg) {\n if (msg.id && (msg as any).method === RPC_METHODS) {\n onMsg(jsonObj({ id: msg.id, result }))\n } else send(msg)\n },\n }\n }\n\nexport const methodsRouter = (\n getMiddleware: (methods: string[]) => Middleware,\n): Middleware =>\n getAsyncMiddleware((onReady, request) => {\n let nTries = 0\n let stopRequest: () => void = noop\n const getMethods = () => {\n nTries++\n stopRequest = request(RPC_METHODS, [], {\n onSuccess: ({ methods }: { methods: string[] }) => {\n onReady(apply(withMethods(methods), getMiddleware(methods)))\n },\n onError: () => {\n if (nTries > 3) onReady(null)\n else {\n const token = setTimeout(getMethods, 500)\n stopRequest = () => clearTimeout(token)\n }\n },\n })\n }\n getMethods()\n\n return () => stopRequest()\n })\n"],"names":[],"mappings":";;;;AAKA,MAAM,WAAA,GAAc,aAAA;AACpB,MAAM,cACJ,CAAC,OAAA,KACD,CAAC,IAAA,KACD,CAAC,OAAO,MAAA,KAAW;AACjB,EAAA,MAAM,MAAA,GAAS,EAAE,OAAA,EAAQ;AACzB,EAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAW,GAAI,IAAA,CAAK,OAAO,MAAM,CAAA;AAC/C,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,KAAK,GAAA,EAAK;AACR,MAAA,IAAI,GAAA,CAAI,EAAA,IAAO,GAAA,CAAY,MAAA,KAAW,WAAA,EAAa;AACjD,QAAA,KAAA,CAAM,QAAQ,EAAE,EAAA,EAAI,IAAI,EAAA,EAAI,MAAA,EAAQ,CAAC,CAAA;AAAA,MACvC,CAAA,WAAY,GAAG,CAAA;AAAA,IACjB;AAAA,GACF;AACF,CAAA;AAEK,MAAM,gBAAgB,CAC3B,aAAA,KAEA,kBAAA,CAAmB,CAAC,SAAS,OAAA,KAAY;AACvC,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,IAAI,WAAA,GAA0B,IAAA;AAC9B,EAAA,MAAM,aAAa,MAAM;AACvB,IAAA,MAAA,EAAA;AACA,IAAA,WAAA,GAAc,OAAA,CAAQ,WAAA,EAAa,EAAC,EAAG;AAAA,MACrC,SAAA,EAAW,CAAC,EAAE,OAAA,EAAQ,KAA6B;AACjD,QAAA,OAAA,CAAQ,MAAM,WAAA,CAAY,OAAO,GAAG,aAAA,CAAc,OAAO,CAAC,CAAC,CAAA;AAAA,MAC7D,CAAA;AAAA,MACA,SAAS,MAAM;AACb,QAAA,IAAI,MAAA,GAAS,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA;AAAA,aACvB;AACH,UAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,UAAA,EAAY,GAAG,CAAA;AACxC,UAAA,WAAA,GAAc,MAAM,aAAa,KAAK,CAAA;AAAA,QACxC;AAAA,MACF;AAAA,KACD,CAAA;AAAA,EACH,CAAA;AACA,EAAA,UAAA,EAAW;AAEX,EAAA,OAAO,MAAM,WAAA,EAAY;AAC3B,CAAC;;;;"}
@@ -0,0 +1,40 @@
1
+ const chainHead = {
2
+ body: "",
3
+ call: "",
4
+ continue: "",
5
+ follow: "",
6
+ header: "",
7
+ stopOperation: "",
8
+ storage: "",
9
+ unfollow: "",
10
+ unpin: ""
11
+ };
12
+ const archive = {
13
+ body: "",
14
+ call: "",
15
+ finalizedHeight: "",
16
+ genesisHash: "",
17
+ hashByHeight: "",
18
+ header: "",
19
+ stopStorage: "",
20
+ storage: ""
21
+ };
22
+ const transaction = {
23
+ broadcast: "",
24
+ stop: ""
25
+ };
26
+ const chainSpec = {
27
+ chainName: "",
28
+ genesisHash: "",
29
+ properties: ""
30
+ };
31
+ Object.entries({ chainHead, chainSpec, transaction, archive }).forEach(
32
+ ([fnGroupName, methods]) => {
33
+ Object.keys(methods).forEach((methodName) => {
34
+ methods[methodName] = `${fnGroupName}_v1_${methodName}`;
35
+ });
36
+ }
37
+ );
38
+
39
+ export { archive, chainHead, chainSpec, transaction };
40
+ //# sourceMappingURL=methods.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"methods.mjs","sources":["../../src/methods.ts"],"sourcesContent":["const chainHead = {\n body: \"\",\n call: \"\",\n continue: \"\",\n follow: \"\",\n header: \"\",\n stopOperation: \"\",\n storage: \"\",\n unfollow: \"\",\n unpin: \"\",\n}\n\nconst archive = {\n body: \"\",\n call: \"\",\n finalizedHeight: \"\",\n genesisHash: \"\",\n hashByHeight: \"\",\n header: \"\",\n stopStorage: \"\",\n storage: \"\",\n}\n\nconst transaction = {\n broadcast: \"\",\n stop: \"\",\n}\n\nconst chainSpec = {\n chainName: \"\",\n genesisHash: \"\",\n properties: \"\",\n}\n\nObject.entries({ chainHead, chainSpec, transaction, archive }).forEach(\n ([fnGroupName, methods]) => {\n Object.keys(methods).forEach((methodName) => {\n ;(methods as any)[methodName] = `${fnGroupName}_v1_${methodName}`\n })\n },\n)\n\nexport { chainHead, transaction, chainSpec, archive }\n"],"names":[],"mappings":"AAAA,MAAM,SAAA,GAAY;AAAA,EAChB,IAAA,EAAM,EAAA;AAAA,EACN,IAAA,EAAM,EAAA;AAAA,EACN,QAAA,EAAU,EAAA;AAAA,EACV,MAAA,EAAQ,EAAA;AAAA,EACR,MAAA,EAAQ,EAAA;AAAA,EACR,aAAA,EAAe,EAAA;AAAA,EACf,OAAA,EAAS,EAAA;AAAA,EACT,QAAA,EAAU,EAAA;AAAA,EACV,KAAA,EAAO;AACT;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,IAAA,EAAM,EAAA;AAAA,EACN,IAAA,EAAM,EAAA;AAAA,EACN,eAAA,EAAiB,EAAA;AAAA,EACjB,WAAA,EAAa,EAAA;AAAA,EACb,YAAA,EAAc,EAAA;AAAA,EACd,MAAA,EAAQ,EAAA;AAAA,EACR,WAAA,EAAa,EAAA;AAAA,EACb,OAAA,EAAS;AACX;AAEA,MAAM,WAAA,GAAc;AAAA,EAClB,SAAA,EAAW,EAAA;AAAA,EACX,IAAA,EAAM;AACR;AAEA,MAAM,SAAA,GAAY;AAAA,EAChB,SAAA,EAAW,EAAA;AAAA,EACX,WAAA,EAAa,EAAA;AAAA,EACb,UAAA,EAAY;AACd;AAEA,MAAA,CAAO,QAAQ,EAAE,SAAA,EAAW,WAAW,WAAA,EAAa,OAAA,EAAS,CAAA,CAAE,OAAA;AAAA,EAC7D,CAAC,CAAC,WAAA,EAAa,OAAO,CAAA,KAAM;AAC1B,IAAA,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,OAAA,CAAQ,CAAC,UAAA,KAAe;AAC1C,MAAC,QAAgB,UAAU,CAAA,GAAI,CAAA,EAAG,WAAW,OAAO,UAAU,CAAA,CAAA;AAAA,IACjE,CAAC,CAAA;AAAA,EACH;AACF,CAAA;;;;"}
@@ -0,0 +1,22 @@
1
+ import { withLegacy } from './legacy/downstream/downstream.mjs';
2
+ import { methodsRouter } from './methods-router.mjs';
3
+ import { modern } from './modern/modern.mjs';
4
+ import './modern/fix-follow.mjs';
5
+ import './modern/fix-premature-blocks.mjs';
6
+ import './modern/fix-unordered-blocks.mjs';
7
+ import './modern/fix-unordered-events.mjs';
8
+ import './methods.mjs';
9
+ import { withNumericIds } from './numeric-ids.mjs';
10
+ import { apply } from './utils/utils.mjs';
11
+
12
+ const modernGroups = ["chainHead", "transaction", "chainSpec", "archive"].map(
13
+ (name) => `${name}_v1`
14
+ );
15
+ const isModern = (methods) => modernGroups.every((group) => methods.some((m) => m.startsWith(group)));
16
+ const middleware = apply(
17
+ withNumericIds,
18
+ methodsRouter((methods) => isModern(methods) ? modern : withLegacy)
19
+ );
20
+
21
+ export { middleware };
22
+ //# sourceMappingURL=middleware.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.mjs","sources":["../../src/middleware.ts"],"sourcesContent":["import { withLegacy } from \"./legacy\"\nimport { methodsRouter } from \"./methods-router\"\nimport { modern } from \"./modern\"\nimport { withNumericIds } from \"./numeric-ids\"\nimport { apply } from \"./utils\"\n\nconst modernGroups = [\"chainHead\", \"transaction\", \"chainSpec\", \"archive\"].map(\n (name) => `${name}_v1`,\n)\nconst isModern = (methods: string[]): boolean =>\n modernGroups.every((group) => methods.some((m) => m.startsWith(group)))\n\nexport const middleware = apply(\n withNumericIds,\n methodsRouter((methods) => (isModern(methods) ? modern : withLegacy)),\n)\n"],"names":[],"mappings":";;;;;;;;;;;AAMA,MAAM,eAAe,CAAC,WAAA,EAAa,aAAA,EAAe,WAAA,EAAa,SAAS,CAAA,CAAE,GAAA;AAAA,EACxE,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,GAAA;AACnB,CAAA;AACA,MAAM,QAAA,GAAW,CAAC,OAAA,KAChB,YAAA,CAAa,MAAM,CAAC,KAAA,KAAU,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,UAAA,CAAW,KAAK,CAAC,CAAC,CAAA;AAEjE,MAAM,UAAA,GAAa,KAAA;AAAA,EACxB,cAAA;AAAA,EACA,cAAc,CAAC,OAAA,KAAa,SAAS,OAAO,CAAA,GAAI,SAAS,UAAW;AACtE;;;;"}
@@ -0,0 +1,79 @@
1
+ import { chainHead } from '../methods.mjs';
2
+
3
+ const { follow, unfollow } = chainHead;
4
+ const resetStops = () => ({ latest: Date.now(), count: 0 });
5
+ const followEnhancer = (base) => (onMsg, onHalt) => {
6
+ const prematureStops = /* @__PURE__ */ new Map();
7
+ const preOpId = /* @__PURE__ */ new Map();
8
+ const onGoing = /* @__PURE__ */ new Set();
9
+ let nStops = resetStops();
10
+ const cleanup = () => {
11
+ [prematureStops, preOpId, onGoing].forEach((x) => {
12
+ x.clear();
13
+ });
14
+ };
15
+ const forceDisconnect = () => {
16
+ disconnect();
17
+ cleanup();
18
+ onHalt();
19
+ };
20
+ const { send, disconnect } = base(
21
+ (parsed) => {
22
+ if ("id" in parsed) {
23
+ const { id, result } = parsed;
24
+ const msg = preOpId.get(id);
25
+ if (msg) {
26
+ preOpId.delete(id);
27
+ const prematureStop = prematureStops.get(result);
28
+ if (prematureStop) {
29
+ prematureStops.delete(result);
30
+ onMsg(parsed);
31
+ onMsg(prematureStop);
32
+ return;
33
+ }
34
+ onGoing.add(result);
35
+ const currentSize = onGoing.size + preOpId.size;
36
+ if (currentSize > 2)
37
+ console.warn(
38
+ `Too many chainHead follow subscriptions (${currentSize})`
39
+ );
40
+ else if (parsed.error) {
41
+ console.warn(`chainHead follow failed on the ${currentSize} sub`);
42
+ forceDisconnect();
43
+ return;
44
+ }
45
+ }
46
+ } else {
47
+ const { subscription, result } = parsed.params;
48
+ if (result?.event === "stop") {
49
+ const diff = Date.now() - nStops.latest;
50
+ nStops.latest += diff;
51
+ nStops.count = diff < 1e3 ? nStops.count + 1 : 1;
52
+ if (onGoing.has(subscription)) onGoing.delete(subscription);
53
+ else prematureStops.set(subscription, parsed);
54
+ }
55
+ }
56
+ onMsg(parsed);
57
+ if (nStops.count > 2) {
58
+ nStops = resetStops();
59
+ forceDisconnect();
60
+ }
61
+ },
62
+ (e) => {
63
+ cleanup();
64
+ onHalt(e);
65
+ }
66
+ );
67
+ return {
68
+ send(parsed) {
69
+ const { method } = parsed;
70
+ if (method === follow) preOpId.set(parsed.id, parsed);
71
+ else if (method === unfollow) onGoing.delete(parsed.params[0]);
72
+ send(parsed);
73
+ },
74
+ disconnect
75
+ };
76
+ };
77
+
78
+ export { followEnhancer };
79
+ //# sourceMappingURL=fix-follow.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-follow.mjs","sources":["../../../src/modern/fix-follow.ts"],"sourcesContent":["import { chainHead } from \"../methods\"\nimport type { Middleware } from \"../types\"\n\nconst { follow, unfollow } = chainHead\nconst resetStops = () => ({ latest: Date.now(), count: 0 })\n\nexport const followEnhancer: Middleware = (base) => (onMsg, onHalt) => {\n const prematureStops = new Map<string, any>()\n const preOpId = new Map<string, any>()\n const onGoing = new Set<string>()\n let nStops: { latest: number; count: number } = resetStops()\n const cleanup = () => {\n ;[prematureStops, preOpId, onGoing].forEach((x) => {\n x.clear()\n })\n }\n\n const forceDisconnect = () => {\n disconnect()\n cleanup()\n onHalt()\n }\n\n const { send, disconnect } = base(\n (parsed: any) => {\n // it's a response\n if (\"id\" in parsed) {\n const { id, result } = parsed\n\n const msg = preOpId.get(id)\n if (msg) {\n preOpId.delete(id)\n const prematureStop = prematureStops.get(result)\n if (prematureStop) {\n prematureStops.delete(result)\n onMsg(parsed)\n onMsg(prematureStop)\n return\n }\n\n onGoing.add(result)\n const currentSize = onGoing.size + preOpId.size\n if (currentSize > 2)\n console.warn(\n `Too many chainHead follow subscriptions (${currentSize})`,\n )\n else if (parsed.error) {\n console.warn(`chainHead follow failed on the ${currentSize} sub`)\n forceDisconnect()\n return\n }\n }\n } else {\n // it's a notifiaction\n const { subscription, result } = (parsed as any).params\n if (result?.event === \"stop\") {\n const diff = Date.now() - nStops.latest\n nStops.latest += diff\n nStops.count = diff < 1000 ? nStops.count + 1 : 1\n\n if (onGoing.has(subscription)) onGoing.delete(subscription)\n else prematureStops.set(subscription, parsed)\n }\n }\n\n onMsg(parsed)\n if (nStops.count > 2) {\n nStops = resetStops()\n forceDisconnect()\n }\n },\n (e) => {\n cleanup()\n onHalt(e)\n },\n )\n\n return {\n send(parsed: any) {\n const { method } = parsed\n if (method === follow) preOpId.set(parsed.id, parsed)\n else if (method === unfollow) onGoing.delete(parsed.params[0])\n send(parsed)\n },\n disconnect,\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { chainHead } from '../methods.mjs';
2
+
3
+ const { follow, unpin, unfollow } = chainHead;
4
+ const fixPrematureBlocks = (base) => (onMsg, onHalt) => {
5
+ const pendingChainHeadSubs = /* @__PURE__ */ new Set();
6
+ const pinnedBlocksInSub = /* @__PURE__ */ new Map();
7
+ const prematureBlocks = /* @__PURE__ */ new Map();
8
+ const withClear = (fn) => (...args) => {
9
+ [pendingChainHeadSubs, pinnedBlocksInSub, prematureBlocks].forEach(
10
+ (x) => {
11
+ x.clear();
12
+ }
13
+ );
14
+ fn(...args);
15
+ };
16
+ const { send: originalSend, disconnect } = base((message) => {
17
+ if ("id" in message) {
18
+ onMsg(message);
19
+ const { id, result } = message;
20
+ if (pendingChainHeadSubs.has(id)) {
21
+ pendingChainHeadSubs.delete(id);
22
+ pinnedBlocksInSub.set(result, /* @__PURE__ */ new Set());
23
+ prematureBlocks.set(result, /* @__PURE__ */ new Map());
24
+ return;
25
+ }
26
+ } else {
27
+ const { subscription } = message.params;
28
+ const pinnedBlocks = pinnedBlocksInSub.get(subscription);
29
+ const prematureSub = prematureBlocks.get(subscription);
30
+ if (pinnedBlocks) {
31
+ const result = message.params.result;
32
+ const { event } = result;
33
+ if (event === "initialized") {
34
+ result.finalizedBlockHashes.forEach((hash) => {
35
+ pinnedBlocks.add(hash);
36
+ });
37
+ }
38
+ if (event === "newBlock") {
39
+ const { parentBlockHash } = result;
40
+ if (!pinnedBlocks.has(parentBlockHash)) {
41
+ const list = prematureSub.get(parentBlockHash) ?? [];
42
+ list.push(message);
43
+ prematureSub.set(parentBlockHash, list);
44
+ return;
45
+ }
46
+ const hash = result.blockHash;
47
+ pinnedBlocks.add(result.blockHash);
48
+ onMsg(message);
49
+ const prematureMessages = prematureSub.get(hash);
50
+ if (prematureMessages) {
51
+ prematureSub.delete(hash);
52
+ prematureMessages.forEach((msg) => {
53
+ pinnedBlocks.add(msg.params.result.blockHash);
54
+ onMsg(msg);
55
+ });
56
+ }
57
+ return;
58
+ }
59
+ if (event === "stop") {
60
+ pinnedBlocks.delete(subscription);
61
+ prematureBlocks.delete(subscription);
62
+ }
63
+ }
64
+ onMsg(message);
65
+ }
66
+ }, withClear(onHalt));
67
+ const send = (msg) => {
68
+ const subId = msg.params[0];
69
+ switch (msg.method) {
70
+ case follow:
71
+ pendingChainHeadSubs.add(msg.id);
72
+ break;
73
+ case unpin:
74
+ const [subscription, blocks] = msg.params;
75
+ blocks.forEach((block) => {
76
+ pinnedBlocksInSub.get(subscription)?.delete(block);
77
+ prematureBlocks.get(subscription)?.delete(block);
78
+ });
79
+ break;
80
+ case unfollow:
81
+ pinnedBlocksInSub.delete(subId);
82
+ prematureBlocks.delete(subId);
83
+ break;
84
+ }
85
+ originalSend(msg);
86
+ };
87
+ return {
88
+ send,
89
+ disconnect: withClear(disconnect)
90
+ };
91
+ };
92
+
93
+ export { fixPrematureBlocks };
94
+ //# sourceMappingURL=fix-premature-blocks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-premature-blocks.mjs","sources":["../../../src/modern/fix-premature-blocks.ts"],"sourcesContent":["import { chainHead } from \"../methods\"\nimport type { Middleware } from \"../types\"\nimport { JsonRpcMessage } from \"@polkadot-api/json-rpc-provider\"\n\ninterface InitializedRpc {\n event: \"initialized\"\n finalizedBlockHashes: string[]\n}\n\ninterface NewBlockRpc {\n event: \"newBlock\"\n blockHash: string\n parentBlockHash: string\n}\n\ninterface BestBlockChangedRpc {\n event: \"bestBlockChanged\"\n bestBlockHash: string\n}\n\ninterface FinalizedRpc {\n event: \"finalized\"\n finalizedBlockHashes: Array<string>\n prunedBlockHashes: Array<string>\n}\n\nexport interface StopRpc {\n event: \"stop\"\n}\n\ntype FollowEvent =\n | InitializedRpc\n | NewBlockRpc\n | BestBlockChangedRpc\n | FinalizedRpc\n | StopRpc\n\nconst { follow, unpin, unfollow } = chainHead\nexport const fixPrematureBlocks: Middleware = (base) => (onMsg, onHalt) => {\n const pendingChainHeadSubs = new Set<string>()\n const pinnedBlocksInSub = new Map<string, Set<string>>()\n const prematureBlocks = new Map<string, Map<string, Array<JsonRpcMessage>>>()\n const withClear =\n <Args extends Array<any>>(\n fn: (...args: Args) => void,\n ): ((...args: Args) => void) =>\n (...args) => {\n ;[pendingChainHeadSubs, pinnedBlocksInSub, prematureBlocks].forEach(\n (x) => {\n x.clear()\n },\n )\n fn(...args)\n }\n\n const { send: originalSend, disconnect } = base((message) => {\n // it's a response\n if (\"id\" in message) {\n onMsg(message)\n const { id, result } = message as unknown as {\n id: string\n result: string\n }\n\n if (pendingChainHeadSubs.has(id)) {\n pendingChainHeadSubs.delete(id)\n pinnedBlocksInSub.set(result, new Set())\n prematureBlocks.set(result, new Map())\n return\n }\n } else {\n // it's a notification\n const { subscription } = (message as any).params\n const pinnedBlocks = pinnedBlocksInSub.get(subscription)\n const prematureSub = prematureBlocks.get(subscription)!\n if (pinnedBlocks) {\n const result = (message as any).params.result as FollowEvent\n const { event } = result\n if (event === \"initialized\") {\n result.finalizedBlockHashes.forEach((hash) => {\n pinnedBlocks.add(hash)\n })\n }\n\n if (event === \"newBlock\") {\n const { parentBlockHash } = result\n if (!pinnedBlocks.has(parentBlockHash)) {\n const list = prematureSub.get(parentBlockHash) ?? []\n list.push(message)\n prematureSub.set(parentBlockHash, list)\n return\n }\n\n const hash = result.blockHash\n pinnedBlocks.add(result.blockHash)\n onMsg(message)\n\n const prematureMessages = prematureSub.get(hash)\n if (prematureMessages) {\n prematureSub.delete(hash)\n prematureMessages.forEach((msg) => {\n pinnedBlocks.add((msg as any).params.result.blockHash)\n onMsg(msg)\n })\n }\n return\n }\n\n if (event === \"stop\") {\n pinnedBlocks.delete(subscription)\n prematureBlocks.delete(subscription)\n }\n }\n onMsg(message)\n }\n }, withClear(onHalt))\n\n const send = (msg: any) => {\n const subId = msg.params[0]\n switch (msg.method) {\n case follow:\n pendingChainHeadSubs.add(msg.id)\n break\n\n case unpin:\n const [subscription, blocks] = msg.params as [string, string[]]\n blocks.forEach((block) => {\n pinnedBlocksInSub.get(subscription)?.delete(block)\n prematureBlocks.get(subscription)?.delete(block)\n })\n break\n\n case unfollow:\n pinnedBlocksInSub.delete(subId)\n prematureBlocks.delete(subId)\n break\n }\n originalSend(msg)\n }\n\n return {\n send,\n disconnect: withClear(disconnect),\n }\n}\n"],"names":[],"mappings":"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"}