@polkadot-api/ws-middleware 1.0.0-canary.22b2fd2

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/esm/index.mjs +13 -0
  4. package/dist/esm/index.mjs.map +1 -0
  5. package/dist/esm/legacy/downstream/archive.mjs +98 -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-missing-initial-best.mjs +66 -0
  48. package/dist/esm/modern/fix-missing-initial-best.mjs.map +1 -0
  49. package/dist/esm/modern/fix-premature-blocks.mjs +94 -0
  50. package/dist/esm/modern/fix-premature-blocks.mjs.map +1 -0
  51. package/dist/esm/modern/fix-unordered-blocks.mjs +100 -0
  52. package/dist/esm/modern/fix-unordered-blocks.mjs.map +1 -0
  53. package/dist/esm/modern/fix-unordered-events.mjs +101 -0
  54. package/dist/esm/modern/fix-unordered-events.mjs.map +1 -0
  55. package/dist/esm/modern/modern.mjs +21 -0
  56. package/dist/esm/modern/modern.mjs.map +1 -0
  57. package/dist/esm/modern/patch-chainhead-events.mjs +16 -0
  58. package/dist/esm/modern/patch-chainhead-events.mjs.map +1 -0
  59. package/dist/esm/modern/unpin-hash.mjs +22 -0
  60. package/dist/esm/modern/unpin-hash.mjs.map +1 -0
  61. package/dist/esm/numeric-ids.mjs +37 -0
  62. package/dist/esm/numeric-ids.mjs.map +1 -0
  63. package/dist/esm/utils/get-async-middleware.mjs +60 -0
  64. package/dist/esm/utils/get-async-middleware.mjs.map +1 -0
  65. package/dist/esm/utils/utils.mjs +22 -0
  66. package/dist/esm/utils/utils.mjs.map +1 -0
  67. package/dist/index.d.ts +29 -0
  68. package/dist/index.js +1782 -0
  69. package/dist/index.js.map +1 -0
  70. package/package.json +57 -0
@@ -0,0 +1,48 @@
1
+ import { catchError, concat, timer, takeUntil, ignoreElements } from 'rxjs';
2
+ import { createOpaqueToken } from '../utils/create-opaque-token.mjs';
3
+ import { transaction } from '../../methods.mjs';
4
+
5
+ const { stop, broadcast } = transaction;
6
+ const createTransactionFns = (upstream, reply) => {
7
+ const ongoing = /* @__PURE__ */ new Map();
8
+ const result = (rId, method, args) => {
9
+ if (method === stop) {
10
+ const [token] = args;
11
+ ongoing.get(token)?.unsubscribe();
12
+ ongoing.delete(token);
13
+ reply(rId, null);
14
+ } else if (method === broadcast) {
15
+ const token = createOpaqueToken();
16
+ ongoing.set(
17
+ token,
18
+ upstream.obsRequest("author_submitExtrinsic", args).pipe(
19
+ // We want to make sure that we keep on retrying if there
20
+ // are errors with the `author_submitExtrinsic` request
21
+ catchError((_, source) => concat(timer(5e3), source)),
22
+ // This logic ensures that the subscription dies if an
23
+ // upstream error (like the client being destroyed) takes place
24
+ takeUntil(
25
+ upstream.finalized$.pipe(
26
+ ignoreElements(),
27
+ catchError(() => {
28
+ ongoing.delete(token);
29
+ return [null];
30
+ })
31
+ )
32
+ )
33
+ ).subscribe()
34
+ );
35
+ reply(rId, token);
36
+ } else {
37
+ throw null;
38
+ }
39
+ };
40
+ result.stop = () => {
41
+ ongoing.forEach((s) => s.unsubscribe());
42
+ ongoing.clear();
43
+ };
44
+ return result;
45
+ };
46
+
47
+ export { createTransactionFns };
48
+ //# sourceMappingURL=transaction.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.mjs","sources":["../../../../src/legacy/downstream/transaction.ts"],"sourcesContent":["import {\n catchError,\n concat,\n ignoreElements,\n Subscription,\n takeUntil,\n timer,\n} from \"rxjs\"\nimport { createUpstream } from \"../upstream/upstream\"\nimport { createOpaqueToken } from \"../utils/create-opaque-token\"\nimport { transaction } from \"../../methods\"\n\nconst { stop, broadcast } = transaction\nexport const createTransactionFns = (\n upstream: ReturnType<typeof createUpstream>,\n reply: (id: string, result: any) => void,\n) => {\n const ongoing = new Map<string, Subscription>()\n const result = (rId: string, method: string, args: any[]) => {\n if (method === stop) {\n const [token] = args\n ongoing.get(token)?.unsubscribe()\n ongoing.delete(token)\n reply(rId, null)\n } else if (method === broadcast) {\n const token = createOpaqueToken()\n ongoing.set(\n token,\n upstream\n .obsRequest(\"author_submitExtrinsic\", args)\n .pipe(\n // We want to make sure that we keep on retrying if there\n // are errors with the `author_submitExtrinsic` request\n catchError((_, source) => concat(timer(5_000), source)),\n // This logic ensures that the subscription dies if an\n // upstream error (like the client being destroyed) takes place\n takeUntil(\n upstream.finalized$.pipe(\n ignoreElements(),\n catchError(() => {\n ongoing.delete(token)\n return [null]\n }),\n ),\n ),\n )\n .subscribe(),\n )\n reply(rId, token)\n } else {\n throw null\n }\n }\n\n result.stop = () => {\n ongoing.forEach((s) => s.unsubscribe())\n ongoing.clear()\n }\n\n return result\n}\n"],"names":[],"mappings":";;;;AAYA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAU,GAAI,WAAA;AACrB,MAAM,oBAAA,GAAuB,CAClC,QAAA,EACA,KAAA,KACG;AACH,EAAA,MAAM,OAAA,uBAAc,GAAA,EAA0B;AAC9C,EAAA,MAAM,MAAA,GAAS,CAAC,GAAA,EAAa,MAAA,EAAgB,IAAA,KAAgB;AAC3D,IAAA,IAAI,WAAW,IAAA,EAAM;AACnB,MAAA,MAAM,CAAC,KAAK,CAAA,GAAI,IAAA;AAChB,MAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG,WAAA,EAAY;AAChC,MAAA,OAAA,CAAQ,OAAO,KAAK,CAAA;AACpB,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB,CAAA,MAAA,IAAW,WAAW,SAAA,EAAW;AAC/B,MAAA,MAAM,QAAQ,iBAAA,EAAkB;AAChC,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,KAAA;AAAA,QACA,QAAA,CACG,UAAA,CAAW,wBAAA,EAA0B,IAAI,CAAA,CACzC,IAAA;AAAA;AAAA;AAAA,UAGC,UAAA,CAAW,CAAC,CAAA,EAAG,MAAA,KAAW,OAAO,KAAA,CAAM,GAAK,CAAA,EAAG,MAAM,CAAC,CAAA;AAAA;AAAA;AAAA,UAGtD,SAAA;AAAA,YACE,SAAS,UAAA,CAAW,IAAA;AAAA,cAClB,cAAA,EAAe;AAAA,cACf,WAAW,MAAM;AACf,gBAAA,OAAA,CAAQ,OAAO,KAAK,CAAA;AACpB,gBAAA,OAAO,CAAC,IAAI,CAAA;AAAA,cACd,CAAC;AAAA;AACH;AACF,UAED,SAAA;AAAU,OACf;AACA,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB,CAAA,MAAO;AACL,MAAA,MAAM,IAAA;AAAA,IACR;AAAA,EACF,CAAA;AAEA,EAAA,MAAA,CAAO,OAAO,MAAM;AAClB,IAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AACtC,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB,CAAA;AAEA,EAAA,OAAO,MAAA;AACT;;;;"}
@@ -0,0 +1,309 @@
1
+ import { Subject, concatMap, of, filter, debounceTime, take, share, takeWhile, merge, map, mergeMap, defer, concat, tap } from 'rxjs';
2
+ import { shareLatest } from '../../utils/share-latest.mjs';
3
+
4
+ const getBlocks = ({
5
+ allHeads$,
6
+ finalized$: finalizedWire$,
7
+ getHeader$,
8
+ hasher$,
9
+ getRecursiveHeader
10
+ }) => {
11
+ const connectedBlocks = {
12
+ blocks: /* @__PURE__ */ new Map(),
13
+ prevFin: "",
14
+ finalized: "",
15
+ best: ""
16
+ };
17
+ const getTree = (root, result = []) => {
18
+ result.push(root);
19
+ connectedBlocks.blocks.get(root).children.forEach((c) => {
20
+ getTree(c, result);
21
+ });
22
+ return result;
23
+ };
24
+ const addBlock = (block) => {
25
+ const { blocks } = connectedBlocks;
26
+ const { hash, parent } = block;
27
+ const me = {
28
+ ...block,
29
+ children: /* @__PURE__ */ new Set(),
30
+ usages: /* @__PURE__ */ new Set()
31
+ };
32
+ blocks.set(hash, me);
33
+ blocks.get(parent)?.children.add(hash);
34
+ return me;
35
+ };
36
+ const setBestFromFinalized = () => {
37
+ connectedBlocks.best = connectedBlocks.finalized;
38
+ let bestHeight = 0;
39
+ const { finalized, blocks } = connectedBlocks;
40
+ getTree(finalized).map((x) => blocks.get(x)).forEach((x) => {
41
+ if (x.number > bestHeight) {
42
+ bestHeight = x.number;
43
+ connectedBlocks.best = x.hash;
44
+ }
45
+ });
46
+ };
47
+ const pendingBlocks = /* @__PURE__ */ new Map();
48
+ const trimPending = (root) => {
49
+ const desc = [...pendingBlocks.get(root).children];
50
+ pendingBlocks.delete(root);
51
+ desc.forEach(trimPending);
52
+ };
53
+ const getPendingTree = (root, result = []) => {
54
+ const me = pendingBlocks.get(root);
55
+ if (!me.header) return result;
56
+ result.push(me.header);
57
+ me.children.forEach((c) => {
58
+ getPendingTree(c, result);
59
+ });
60
+ return result;
61
+ };
62
+ const _newBlocks$ = new Subject();
63
+ const onError = (e) => _newBlocks$.error(e);
64
+ const _finalized$ = finalizedWire$.pipe(
65
+ concatMap((header, idx) => {
66
+ const { hash } = header;
67
+ if (!idx) {
68
+ addBlock(header);
69
+ connectedBlocks.finalized = connectedBlocks.best = header.hash;
70
+ }
71
+ return connectedBlocks.blocks.has(hash) ? of(hash) : _newBlocks$.pipe(
72
+ filter((x) => x === hash),
73
+ // some of the following blocks could be prunned b/c of this finalized event.
74
+ // So, we have to make sure that this "batch" of _newBlocks has been flushed.
75
+ debounceTime(0),
76
+ take(1)
77
+ );
78
+ }),
79
+ share()
80
+ );
81
+ allHeads$.subscribe((header) => {
82
+ const { parent, hash, number } = header;
83
+ if (connectedBlocks.blocks.has(hash) || !number) return;
84
+ if (connectedBlocks.blocks.has(parent)) {
85
+ addBlock(header);
86
+ _newBlocks$.next(hash);
87
+ } else {
88
+ pendingBlocks.set(hash, {
89
+ hash: header.hash,
90
+ header,
91
+ children: /* @__PURE__ */ new Set()
92
+ });
93
+ if (!pendingBlocks.has(parent)) {
94
+ pendingBlocks.set(parent, {
95
+ hash: parent,
96
+ header: null,
97
+ children: /* @__PURE__ */ new Set()
98
+ });
99
+ getRecursiveHeader(parent).pipe(
100
+ takeWhile((result) => {
101
+ let me = pendingBlocks.get(result.hash);
102
+ if (!me) return false;
103
+ me.header = result;
104
+ const finalized = connectedBlocks.blocks.get(
105
+ connectedBlocks.finalized
106
+ );
107
+ if (finalized && result.number <= finalized.number) {
108
+ while (pendingBlocks.has(me.header?.parent ?? ""))
109
+ me = pendingBlocks.get(me.header.parent);
110
+ trimPending(me.hash);
111
+ return false;
112
+ }
113
+ if (connectedBlocks.blocks.has(result.parent)) {
114
+ let target = connectedBlocks.blocks.get(result.parent);
115
+ const diff = target.number - finalized.number;
116
+ for (let i = 0; i < diff; i++) {
117
+ const nextTarget = connectedBlocks.blocks.get(target.parent);
118
+ if (!nextTarget) break;
119
+ target = nextTarget;
120
+ }
121
+ if (target === finalized) {
122
+ const pendingOnes = getPendingTree(result.hash);
123
+ pendingOnes.forEach((h) => {
124
+ pendingBlocks.delete(h.hash);
125
+ addBlock(h);
126
+ _newBlocks$.next(h.hash);
127
+ });
128
+ } else trimPending(result.hash);
129
+ return false;
130
+ }
131
+ const pendingParent = pendingBlocks.get(result.parent);
132
+ if (pendingParent) {
133
+ pendingParent.children.add(result.hash);
134
+ return false;
135
+ }
136
+ pendingBlocks.set(result.parent, {
137
+ hash: result.parent,
138
+ header: null,
139
+ children: /* @__PURE__ */ new Set([result.hash])
140
+ });
141
+ return true;
142
+ })
143
+ ).subscribe({ error: onError });
144
+ }
145
+ pendingBlocks.get(parent).children.add(hash);
146
+ }
147
+ }, onError);
148
+ const getFinalizedEvent = () => {
149
+ const prunedBlockHashes = [];
150
+ const finalizedBlockHashes = [];
151
+ const { blocks, finalized, prevFin } = connectedBlocks;
152
+ let current = blocks.get(finalized);
153
+ let prev = blocks.get(current.parent);
154
+ while (prev) {
155
+ finalizedBlockHashes.push(current.hash);
156
+ prev.children.forEach((c) => {
157
+ if (c !== current.hash) getTree(c, prunedBlockHashes);
158
+ });
159
+ current = prev;
160
+ if (current.hash === prevFin) break;
161
+ prev = blocks.get(current.parent);
162
+ }
163
+ finalizedBlockHashes.reverse();
164
+ return { event: "finalized", prunedBlockHashes, finalizedBlockHashes };
165
+ };
166
+ let activeSubscriptions = /* @__PURE__ */ new Set();
167
+ const getNewBlockEvent = (blockHash) => {
168
+ const block = connectedBlocks.blocks.get(blockHash);
169
+ activeSubscriptions.forEach((subId) => {
170
+ block.usages.add(subId);
171
+ });
172
+ return {
173
+ event: "newBlock",
174
+ blockHash,
175
+ parentBlockHash: block.parent,
176
+ newRuntime: block.hasUpgrade ? {} : null
177
+ };
178
+ };
179
+ const tryRemove = (blockHash, up) => {
180
+ const { blocks } = connectedBlocks;
181
+ const block = blocks.get(blockHash);
182
+ if (!block || block.usages.size > 0) return;
183
+ const { parent, children } = block;
184
+ if (up !== true) children.forEach((c) => tryRemove(c, false));
185
+ if (up !== false) tryRemove(parent, true);
186
+ if (!blocks.has(parent) || !block.children.size) {
187
+ blocks.get(parent)?.children.delete(blockHash);
188
+ blocks.delete(blockHash);
189
+ }
190
+ };
191
+ const updates$ = merge(
192
+ _newBlocks$.pipe(
193
+ map((hash) => ({
194
+ type: "new",
195
+ value: connectedBlocks.blocks.get(hash)
196
+ }))
197
+ ),
198
+ _finalized$.pipe(map((hash) => ({ type: "fin", value: hash })))
199
+ ).pipe(
200
+ mergeMap((x) => {
201
+ if (x.type === "new") {
202
+ const block = x.value;
203
+ const { hash } = block;
204
+ addBlock(block);
205
+ const result2 = [getNewBlockEvent(hash)];
206
+ if (block.number > connectedBlocks.blocks.get(connectedBlocks.best).number) {
207
+ connectedBlocks.best = hash;
208
+ result2.push({ event: "bestBlockChanged", bestBlockHash: hash });
209
+ }
210
+ return result2;
211
+ }
212
+ connectedBlocks.prevFin = connectedBlocks.finalized;
213
+ connectedBlocks.finalized = x.value;
214
+ let prevBest = connectedBlocks.best;
215
+ setBestFromFinalized();
216
+ const result = [getFinalizedEvent()];
217
+ if (prevBest !== connectedBlocks.best)
218
+ result.unshift({
219
+ event: "bestBlockChanged",
220
+ bestBlockHash: connectedBlocks.best
221
+ });
222
+ return result;
223
+ }),
224
+ share()
225
+ );
226
+ const ready$ = defer(
227
+ () => connectedBlocks.blocks.size ? [null] : _finalized$.pipe(
228
+ take(1),
229
+ map(() => null)
230
+ )
231
+ ).pipe(shareLatest);
232
+ const finalized$ = _finalized$.pipe(
233
+ map((hash) => connectedBlocks.blocks.get(hash)),
234
+ shareLatest
235
+ );
236
+ merge(updates$, finalized$).subscribe({
237
+ error: onError
238
+ });
239
+ const upstream = (subId) => {
240
+ const getInitialized = () => {
241
+ const { blocks, finalized } = connectedBlocks;
242
+ const finalizedBlockHashes = [];
243
+ let current = blocks.get(finalized);
244
+ while (current && finalizedBlockHashes.length < 10) {
245
+ finalizedBlockHashes.push(current.hash);
246
+ current.usages.add(subId);
247
+ current = blocks.get(current.parent);
248
+ }
249
+ finalizedBlockHashes.reverse();
250
+ return {
251
+ event: "initialized",
252
+ finalizedBlockHashes
253
+ };
254
+ };
255
+ const unpin = (blockHash) => {
256
+ const block = connectedBlocks.blocks.get(blockHash);
257
+ if (block) {
258
+ block.usages.delete(subId);
259
+ tryRemove(blockHash);
260
+ }
261
+ };
262
+ const initialEvents$ = ready$.pipe(
263
+ mergeMap(() => {
264
+ const { best, finalized } = connectedBlocks;
265
+ const others = getTree(
266
+ finalized
267
+ ).slice(1).map(getNewBlockEvent);
268
+ others.push({
269
+ event: "bestBlockChanged",
270
+ bestBlockHash: best
271
+ });
272
+ return [getInitialized(), ...others];
273
+ })
274
+ );
275
+ return {
276
+ blocks$: concat(initialEvents$, updates$).pipe(
277
+ tap({
278
+ subscribe: () => {
279
+ activeSubscriptions.add(subId);
280
+ },
281
+ finalize: () => {
282
+ activeSubscriptions.delete(subId);
283
+ }
284
+ }),
285
+ share()
286
+ ),
287
+ getHeader: (blockHash) => connectedBlocks.blocks.get(blockHash)?.header ?? null,
288
+ isPinned: (blockHash) => !!connectedBlocks.blocks.get(blockHash)?.usages.has(subId),
289
+ unpin
290
+ };
291
+ };
292
+ const clean = () => {
293
+ pendingBlocks.clear();
294
+ connectedBlocks.blocks.clear();
295
+ };
296
+ return {
297
+ clean,
298
+ upstream,
299
+ finalized$,
300
+ getHeader$: (hash) => {
301
+ const block = connectedBlocks.blocks.get(hash);
302
+ return block ? of(block) : getHeader$(hash);
303
+ },
304
+ hasher$
305
+ };
306
+ };
307
+
308
+ export { getBlocks };
309
+ //# sourceMappingURL=blocks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.mjs","sources":["../../../../../src/legacy/upstream/blocks/blocks.ts"],"sourcesContent":["import {\n concat,\n concatMap,\n debounceTime,\n defer,\n filter,\n map,\n merge,\n mergeMap,\n Observable,\n of,\n share,\n Subject,\n take,\n takeWhile,\n tap,\n} from \"rxjs\"\nimport { HexString } from \"@polkadot-api/substrate-bindings\"\nimport type {\n BestBlockChangedEvent,\n DecentHeader,\n InitializedEvent,\n NewBlockEvent,\n} from \"../../types\"\nimport { UpstreamEvents } from \"./upstream-events\"\nimport { shareLatest } from \"../../utils/share-latest\"\n\nexport const getBlocks = ({\n allHeads$,\n finalized$: finalizedWire$,\n getHeader$,\n hasher$,\n getRecursiveHeader,\n}: UpstreamEvents) => {\n const connectedBlocks = {\n blocks: new Map<\n string,\n DecentHeader & {\n children: Set<string>\n usages: Set<string>\n }\n >(),\n prevFin: \"\",\n finalized: \"\",\n best: \"\",\n }\n\n const getTree = (root: string, result: string[] = []): string[] => {\n result.push(root)\n connectedBlocks.blocks.get(root)!.children.forEach((c) => {\n getTree(c, result)\n })\n return result\n }\n\n const addBlock = (block: DecentHeader) => {\n const { blocks } = connectedBlocks\n const { hash, parent } = block\n const me = {\n ...block,\n children: new Set<string>(),\n usages: new Set<string>(),\n }\n blocks.set(hash, me)\n blocks.get(parent)?.children.add(hash)\n return me\n }\n\n const setBestFromFinalized = () => {\n connectedBlocks.best = connectedBlocks.finalized\n let bestHeight = 0\n const { finalized, blocks } = connectedBlocks\n getTree(finalized)\n .map((x) => blocks.get(x)!)\n .forEach((x) => {\n if (x.number > bestHeight) {\n bestHeight = x.number\n connectedBlocks.best = x.hash\n }\n })\n }\n\n const pendingBlocks = new Map<\n string,\n {\n hash: string\n header: DecentHeader | null\n children: Set<string>\n }\n >()\n\n const trimPending = (root: string) => {\n const desc = [...pendingBlocks.get(root)!.children]\n pendingBlocks.delete(root)\n desc.forEach(trimPending)\n }\n\n const getPendingTree = (\n root: string,\n result: Array<DecentHeader> = [],\n ): Array<DecentHeader> => {\n const me = pendingBlocks.get(root)!\n if (!me.header) return result\n result.push(me.header)\n me!.children.forEach((c) => {\n getPendingTree(c, result)\n })\n return result\n }\n\n const _newBlocks$ = new Subject<string>()\n const onError = (e: any) => _newBlocks$.error(e)\n\n const _finalized$ = finalizedWire$.pipe(\n concatMap((header, idx) => {\n const { hash } = header\n if (!idx) {\n addBlock(header)\n connectedBlocks.finalized = connectedBlocks.best = header.hash\n }\n return connectedBlocks.blocks.has(hash)\n ? of(hash)\n : _newBlocks$.pipe(\n filter((x) => x === hash),\n // some of the following blocks could be prunned b/c of this finalized event.\n // So, we have to make sure that this \"batch\" of _newBlocks has been flushed.\n debounceTime(0),\n take(1),\n )\n }),\n share(),\n )\n\n allHeads$.subscribe((header) => {\n const { parent, hash, number } = header\n if (connectedBlocks.blocks.has(hash) || !number) return\n\n if (connectedBlocks.blocks.has(parent)) {\n addBlock(header)\n _newBlocks$.next(hash)\n } else {\n pendingBlocks.set(hash, {\n hash: header.hash,\n header,\n children: new Set<string>(),\n })\n\n if (!pendingBlocks.has(parent)) {\n pendingBlocks.set(parent, {\n hash: parent,\n header: null,\n children: new Set(),\n })\n\n getRecursiveHeader(parent)\n .pipe(\n takeWhile((result) => {\n let me = pendingBlocks.get(result.hash)\n if (!me) return false // it was trimmed before b/c it was a prunned branch\n me.header = result\n\n const finalized = connectedBlocks.blocks.get(\n connectedBlocks.finalized,\n )\n\n // let's check if we have to prune this\n if (finalized && result.number <= finalized.number) {\n while (pendingBlocks.has(me.header?.parent ?? \"\"))\n me = pendingBlocks.get(me.header!.parent)!\n trimPending(me.hash)\n return false\n }\n\n if (connectedBlocks.blocks.has(result.parent)) {\n let target = connectedBlocks.blocks.get(result.parent)!\n const diff = target.number - finalized!.number\n for (let i = 0; i < diff; i++) {\n const nextTarget = connectedBlocks.blocks.get(target.parent)\n if (!nextTarget) break\n target = nextTarget\n }\n\n // it descends from the finalized block, all good...\n if (target === finalized) {\n const pendingOnes = getPendingTree(result.hash)\n pendingOnes.forEach((h) => {\n pendingBlocks.delete(h.hash)\n addBlock(h)\n _newBlocks$.next(h.hash)\n })\n } else trimPending(result.hash) // it was a pruned branch\n\n return false\n }\n\n const pendingParent = pendingBlocks.get(result.parent)\n // another subscription is loading it already\n if (pendingParent) {\n pendingParent.children.add(result.hash)\n return false\n }\n\n pendingBlocks.set(result.parent, {\n hash: result.parent,\n header: null,\n children: new Set([result.hash]),\n })\n return true\n }),\n )\n .subscribe({ error: onError })\n }\n pendingBlocks.get(parent)!.children.add(hash)\n }\n }, onError)\n\n const getFinalizedEvent = (): {\n event: \"finalized\"\n prunedBlockHashes: string[]\n finalizedBlockHashes: string[]\n } => {\n const prunedBlockHashes: string[] = []\n const finalizedBlockHashes: string[] = []\n const { blocks, finalized, prevFin } = connectedBlocks\n\n let current = blocks.get(finalized)!\n let prev = blocks.get(current.parent)\n while (prev) {\n finalizedBlockHashes.push(current.hash)\n prev.children.forEach((c) => {\n if (c !== current.hash) getTree(c, prunedBlockHashes)\n })\n current = prev\n if (current.hash === prevFin) break\n prev = blocks.get(current.parent)\n }\n finalizedBlockHashes.reverse()\n\n return { event: \"finalized\", prunedBlockHashes, finalizedBlockHashes }\n }\n\n let activeSubscriptions = new Set<string>()\n const getNewBlockEvent = (blockHash: string) => {\n const block = connectedBlocks.blocks.get(blockHash)!\n activeSubscriptions.forEach((subId) => {\n block.usages.add(subId)\n })\n return {\n event: \"newBlock\" as const,\n blockHash,\n parentBlockHash: block.parent,\n newRuntime: block.hasUpgrade\n ? ({} as {\n specName: string\n implName: string\n specVersion: number\n implVersion: number\n transactionVersion: number\n apis: Record<string, number>\n })\n : null,\n }\n }\n\n const tryRemove = (blockHash: string, up?: boolean) => {\n const { blocks } = connectedBlocks\n const block = blocks.get(blockHash)\n if (!block || block.usages.size > 0) return\n\n const { parent, children } = block\n if (up !== true) children.forEach((c) => tryRemove(c, false))\n if (up !== false) tryRemove(parent, true)\n if (!blocks.has(parent) || !block.children.size) {\n blocks.get(parent)?.children.delete(blockHash)\n blocks.delete(blockHash)\n }\n }\n\n const updates$ = merge(\n _newBlocks$.pipe(\n map((hash) => ({\n type: \"new\" as const,\n value: connectedBlocks.blocks.get(hash)!,\n })),\n ),\n _finalized$.pipe(map((hash) => ({ type: \"fin\" as const, value: hash }))),\n ).pipe(\n mergeMap((x) => {\n if (x.type === \"new\") {\n const block = x.value\n const { hash } = block\n addBlock(block)\n const result: Array<\n | ReturnType<typeof getNewBlockEvent>\n | { event: \"bestBlockChanged\"; bestBlockHash: string }\n > = [getNewBlockEvent(hash)]\n if (\n block.number >\n connectedBlocks.blocks.get(connectedBlocks.best)!.number\n ) {\n connectedBlocks.best = hash\n result.push({ event: \"bestBlockChanged\", bestBlockHash: hash })\n }\n return result\n }\n\n connectedBlocks.prevFin = connectedBlocks.finalized\n connectedBlocks.finalized = x.value\n let prevBest = connectedBlocks.best\n setBestFromFinalized()\n const result: Array<\n | ReturnType<typeof getFinalizedEvent>\n | { event: \"bestBlockChanged\"; bestBlockHash: string }\n > = [getFinalizedEvent()]\n\n if (prevBest !== connectedBlocks.best)\n result.unshift({\n event: \"bestBlockChanged\",\n bestBlockHash: connectedBlocks.best,\n })\n return result\n }),\n share(),\n )\n\n const ready$ = defer(() =>\n connectedBlocks.blocks.size\n ? [null]\n : _finalized$.pipe(\n take(1),\n map(() => null),\n ),\n ).pipe(shareLatest)\n\n const finalized$ = _finalized$.pipe(\n map((hash) => connectedBlocks.blocks.get(hash)! as DecentHeader),\n shareLatest,\n )\n\n merge(updates$, finalized$).subscribe({\n error: onError,\n })\n\n const upstream = (subId: string) => {\n const getInitialized = () => {\n const { blocks, finalized } = connectedBlocks\n const finalizedBlockHashes: string[] = []\n let current = blocks.get(finalized)\n while (current && finalizedBlockHashes.length < 10) {\n finalizedBlockHashes.push(current.hash)\n current.usages.add(subId)\n current = blocks.get(current.parent)\n }\n finalizedBlockHashes.reverse()\n\n return {\n event: \"initialized\" as const,\n finalizedBlockHashes,\n }\n }\n\n const unpin = (blockHash: string) => {\n const block = connectedBlocks.blocks.get(blockHash)\n if (block) {\n block.usages.delete(subId)\n tryRemove(blockHash)\n }\n }\n\n const initialEvents$: Observable<\n InitializedEvent | NewBlockEvent | BestBlockChangedEvent\n > = ready$.pipe(\n mergeMap(() => {\n const { best, finalized } = connectedBlocks\n const others: Array<NewBlockEvent | BestBlockChangedEvent> = getTree(\n finalized,\n )\n .slice(1)\n .map(getNewBlockEvent)\n others.push({\n event: \"bestBlockChanged\" as const,\n bestBlockHash: best,\n })\n return [getInitialized(), ...others]\n }),\n )\n\n return {\n blocks$: concat(initialEvents$, updates$).pipe(\n tap({\n subscribe: () => {\n activeSubscriptions.add(subId)\n },\n finalize: () => {\n activeSubscriptions.delete(subId)\n },\n }),\n share(),\n ),\n getHeader: (blockHash: string) =>\n connectedBlocks.blocks.get(blockHash)?.header ?? null,\n isPinned: (blockHash: string) =>\n !!connectedBlocks.blocks.get(blockHash)?.usages.has(subId),\n unpin,\n }\n }\n\n const clean = () => {\n pendingBlocks.clear()\n connectedBlocks.blocks.clear()\n }\n\n return {\n clean,\n upstream,\n finalized$,\n getHeader$: (hash: HexString): Observable<DecentHeader> => {\n const block = connectedBlocks.blocks.get(hash)\n return block ? of(block) : getHeader$(hash)\n },\n hasher$,\n }\n}\n"],"names":["result"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { getBlocks } from './blocks.mjs';
2
+ import { getUpstreamEvents } from './upstream-events.mjs';
3
+
4
+ const getBlocks$ = (request, request$) => getBlocks(getUpstreamEvents(request, request$));
5
+
6
+ export { getBlocks$ };
7
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../../../../src/legacy/upstream/blocks/index.ts"],"sourcesContent":["import type { Observable } from \"rxjs\"\nimport type { ClientRequest } from \"@polkadot-api/raw-client\"\nimport { getBlocks } from \"./blocks\"\nimport { getUpstreamEvents } from \"./upstream-events\"\n\nexport const getBlocks$ = (\n request: ClientRequest<any, any>,\n request$: <Args extends Array<any>, Payload>(\n method: string,\n params: Args,\n ) => Observable<Payload>,\n) => getBlocks(getUpstreamEvents(request, request$))\n"],"names":[],"mappings":";;;AAKO,MAAM,UAAA,GAAa,CACxB,OAAA,EACA,QAAA,KAIG,UAAU,iBAAA,CAAkB,OAAA,EAAS,QAAQ,CAAC;;;;"}
@@ -0,0 +1,92 @@
1
+ import { noop } from '@polkadot-api/utils';
2
+ import { Subject, mergeMap, map, pipe, Observable, concat, of } from 'rxjs';
3
+ import { getFromShittyHeader } from '../../utils/fromShittyHeader.mjs';
4
+ import { getHasherFromBlock } from '../../utils/get-hasher-from-block.mjs';
5
+ import { shareLatest } from '../../utils/share-latest.mjs';
6
+ import { withLatestFromBp } from '../../utils/with-latest-from-bp.mjs';
7
+
8
+ const INITIAL_ERROR = {};
9
+ const getUpstreamEvents = (request, request$) => {
10
+ const firstFinHeader$ = new Subject();
11
+ const hasher$ = firstFinHeader$.pipe(
12
+ mergeMap(
13
+ (h) => request$("chain_getBlockHash", [
14
+ h.number
15
+ ]).pipe(map(getHasherFromBlock(h)))
16
+ ),
17
+ shareLatest
18
+ );
19
+ const fromShittyHeader$ = hasher$.pipe(map(getFromShittyHeader), shareLatest);
20
+ const toNiceHeader = pipe(
21
+ withLatestFromBp(fromShittyHeader$),
22
+ map(([fromShittyHeader, shitHeader]) => fromShittyHeader(shitHeader))
23
+ );
24
+ const getHeaders$ = (startMethod, stopMethod, isFin = false) => new Observable((observer) => {
25
+ const onError = (e) => {
26
+ observer.error(e);
27
+ };
28
+ let stop = null;
29
+ let isFirstFin = isFin;
30
+ request(startMethod, [], {
31
+ onSuccess: (subId, followSub) => {
32
+ const done = followSub(subId, {
33
+ next: (v) => {
34
+ if (isFirstFin) {
35
+ isFirstFin = false;
36
+ firstFinHeader$.next(v);
37
+ firstFinHeader$.complete();
38
+ }
39
+ observer.next(v);
40
+ },
41
+ error: onError
42
+ });
43
+ const unsubscribe = () => {
44
+ done();
45
+ try {
46
+ request(stopMethod, [subId], {
47
+ onError: noop,
48
+ onSuccess: noop
49
+ });
50
+ } catch {
51
+ }
52
+ };
53
+ if (stop !== null) unsubscribe();
54
+ else stop = unsubscribe;
55
+ },
56
+ onError() {
57
+ onError(INITIAL_ERROR);
58
+ }
59
+ });
60
+ return () => {
61
+ stop?.();
62
+ stop = noop;
63
+ };
64
+ }).pipe(toNiceHeader);
65
+ const allHeads$ = getHeaders$(
66
+ "chain_subscribeAllHeads",
67
+ "chain_unsubscribeAllHeads"
68
+ );
69
+ const finalized$ = getHeaders$(
70
+ "chain_subscribeFinalizedHeads",
71
+ "chain_unsubscribeFinalizedHeads",
72
+ true
73
+ );
74
+ const getHeader$ = (hash) => request$("chain_getHeader", [hash]).pipe(
75
+ toNiceHeader
76
+ );
77
+ const getRecursiveHeader = (hash) => getHeader$(hash).pipe(
78
+ mergeMap(
79
+ (header) => concat(of(header), getRecursiveHeader(header.parent))
80
+ )
81
+ );
82
+ return {
83
+ allHeads$,
84
+ finalized$,
85
+ hasher$,
86
+ getRecursiveHeader,
87
+ getHeader$
88
+ };
89
+ };
90
+
91
+ export { getUpstreamEvents };
92
+ //# sourceMappingURL=upstream-events.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream-events.mjs","sources":["../../../../../src/legacy/upstream/blocks/upstream-events.ts"],"sourcesContent":["import { ClientRequest } from \"@polkadot-api/raw-client\"\nimport { HexString } from \"@polkadot-api/substrate-bindings\"\nimport { noop } from \"@polkadot-api/utils\"\nimport { concat, map, mergeMap, Observable, of, pipe, Subject } from \"rxjs\"\nimport { DecentHeader, ShittyHeader } from \"../../types\"\nimport { getFromShittyHeader } from \"../../utils/fromShittyHeader\"\nimport { getHasherFromBlock } from \"../../utils/get-hasher-from-block\"\nimport { shareLatest } from \"../../utils/share-latest\"\nimport { withLatestFromBp } from \"../../utils/with-latest-from-bp\"\n\nconst INITIAL_ERROR = {}\n\nexport const getUpstreamEvents = (\n request: ClientRequest<any, any>,\n request$: <Args extends Array<any>, Payload>(\n method: string,\n params: Args,\n ) => Observable<Payload>,\n) => {\n const firstFinHeader$ = new Subject<ShittyHeader>()\n const hasher$ = firstFinHeader$.pipe(\n mergeMap((h) =>\n request$<[number | string], HexString>(\"chain_getBlockHash\", [\n h.number,\n ]).pipe(map(getHasherFromBlock(h))),\n ),\n shareLatest,\n )\n const fromShittyHeader$ = hasher$.pipe(map(getFromShittyHeader), shareLatest)\n const toNiceHeader = pipe(\n withLatestFromBp<\n (x: ShittyHeader) => ReturnType<ReturnType<typeof getFromShittyHeader>>,\n ShittyHeader\n >(fromShittyHeader$),\n map(([fromShittyHeader, shitHeader]) => fromShittyHeader(shitHeader)),\n )\n\n const getHeaders$ = (\n startMethod: string,\n stopMethod: string,\n isFin = false,\n ): Observable<DecentHeader> =>\n new Observable<ShittyHeader>((observer) => {\n const onError = (e: any) => {\n observer.error(e)\n }\n\n let stop: (() => void) | null = null\n let isFirstFin = isFin\n ;(request as ClientRequest<string, ShittyHeader>)(startMethod, [], {\n onSuccess: (subId, followSub) => {\n const done = followSub(subId, {\n next: (v) => {\n if (isFirstFin) {\n isFirstFin = false\n firstFinHeader$.next(v)\n firstFinHeader$.complete()\n }\n observer.next(v)\n },\n error: onError,\n })\n const unsubscribe = () => {\n done()\n try {\n request(stopMethod, [subId], {\n onError: noop,\n onSuccess: noop,\n })\n } catch {}\n }\n if (stop !== null) unsubscribe()\n else stop = unsubscribe\n },\n onError() {\n onError(INITIAL_ERROR)\n },\n })\n\n return () => {\n stop?.()\n stop = noop\n }\n }).pipe(toNiceHeader)\n\n const allHeads$ = getHeaders$(\n \"chain_subscribeAllHeads\",\n \"chain_unsubscribeAllHeads\",\n )\n\n const finalized$ = getHeaders$(\n \"chain_subscribeFinalizedHeads\",\n \"chain_unsubscribeFinalizedHeads\",\n true,\n )\n\n const getHeader$ = (hash: string) =>\n request$<[string], ShittyHeader>(\"chain_getHeader\", [hash]).pipe(\n toNiceHeader,\n )\n\n const getRecursiveHeader = (hash: string): Observable<DecentHeader> =>\n getHeader$(hash).pipe(\n mergeMap((header) =>\n concat(of(header), getRecursiveHeader(header.parent)),\n ),\n )\n\n return {\n allHeads$,\n finalized$,\n hasher$,\n getRecursiveHeader,\n getHeader$,\n }\n}\n\nexport type UpstreamEvents = ReturnType<typeof getUpstreamEvents>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { validateProofs } from '@polkadot-api/substrate-bindings';
2
+ import { mergeMap } from 'rxjs';
3
+
4
+ const createClosestDescendantMerkleValue = (obsRequest) => (at, key) => obsRequest("state_getReadProof", [[key], at]).pipe(
5
+ mergeMap((x) => {
6
+ const result = validateProofs(x.proof);
7
+ if (!result) throw new Error("Invalid Proof");
8
+ const { rootHash, proofs } = result;
9
+ let winnerHash = rootHash;
10
+ let current = proofs[winnerHash];
11
+ let nKeyChars = 2;
12
+ do {
13
+ const nextOne = proofs[winnerHash];
14
+ if (!nextOne || nextOne.type === "Raw") break;
15
+ current = nextOne;
16
+ winnerHash = void 0;
17
+ if (!current.partialKey.startsWith(
18
+ key.slice(nKeyChars, nKeyChars + current.partialKey.length)
19
+ ))
20
+ return [];
21
+ nKeyChars += current.partialKey.length;
22
+ if ((current.type === "LeafWithHash" || current.type === "BranchWithHash") && proofs[current.value]) {
23
+ winnerHash = current.value;
24
+ continue;
25
+ }
26
+ if ("children" in current) {
27
+ const winner = Object.entries(
28
+ current.children
29
+ ).find(([, hash]) => proofs[hash]);
30
+ if (winner) {
31
+ if (winner[0] !== key[nKeyChars++]) return [];
32
+ winnerHash = winner[1];
33
+ }
34
+ }
35
+ } while (winnerHash);
36
+ return [current.hash];
37
+ })
38
+ );
39
+
40
+ export { createClosestDescendantMerkleValue };
41
+ //# sourceMappingURL=proofs.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proofs.mjs","sources":["../../../../src/legacy/upstream/proofs.ts"],"sourcesContent":["import {\n HexString,\n ProofTrieNode,\n TrieNode,\n validateProofs,\n} from \"@polkadot-api/substrate-bindings\"\nimport { mergeMap, Observable } from \"rxjs\"\n\nexport const createClosestDescendantMerkleValue =\n (\n obsRequest: <Args extends Array<any>, Payload>(\n method: string,\n params: Args,\n ) => Observable<Payload>,\n ) =>\n (at: HexString, key: HexString) =>\n obsRequest<\n [keys: Array<HexString>, at: HexString],\n {\n at: HexString\n proof: HexString[]\n }\n >(\"state_getReadProof\", [[key], at]).pipe(\n mergeMap((x) => {\n const result = validateProofs(x.proof)\n if (!result) throw new Error(\"Invalid Proof\")\n const { rootHash, proofs } = result\n let winnerHash: HexString | undefined = rootHash\n let current: {\n hash: HexString\n parent?: HexString\n } & TrieNode = proofs[winnerHash!] as any\n\n let nKeyChars = 2 // skipping `0x`\n do {\n const nextOne: ProofTrieNode = proofs[winnerHash!]\n if (!nextOne || nextOne.type === \"Raw\") break\n\n current = nextOne\n winnerHash = undefined\n if (\n !current.partialKey.startsWith(\n key.slice(nKeyChars, nKeyChars + current.partialKey.length),\n )\n )\n // This causes the observable to complete, which in its turn triggers an [`operationStorageDone`](https://paritytech.github.io/json-rpc-interface-spec/api/chainHead_v1_follow.html#operationstoragedone)\n // event, without triggering the intermediary `OperationStorageItems` event. This is the expected behaviour when querying a non-existing storage entry.\n return []\n nKeyChars += current.partialKey.length\n if (\n (current.type === \"LeafWithHash\" ||\n current.type === \"BranchWithHash\") &&\n proofs[current.value]\n ) {\n winnerHash = current.value\n continue\n }\n\n if (\"children\" in current) {\n const winner: [string, string] | undefined = Object.entries(\n current.children,\n ).find(([, hash]) => proofs[hash])\n\n if (winner) {\n // Same as before: in this case we know that it won't match with the requested key, so we complete without an emission.\n if (winner[0] !== key[nKeyChars++]) return []\n winnerHash = winner[1]\n }\n }\n } while (winnerHash)\n\n return [current!.hash]\n }),\n )\n"],"names":[],"mappings":";;;AAQO,MAAM,kCAAA,GACX,CACE,UAAA,KAKF,CAAC,IAAe,GAAA,KACd,UAAA,CAME,oBAAA,EAAsB,CAAC,CAAC,GAAG,CAAA,EAAG,EAAE,CAAC,CAAA,CAAE,IAAA;AAAA,EACnC,QAAA,CAAS,CAAC,CAAA,KAAM;AACd,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,CAAA,CAAE,KAAK,CAAA;AACrC,IAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,eAAe,CAAA;AAC5C,IAAA,MAAM,EAAE,QAAA,EAAU,MAAA,EAAO,GAAI,MAAA;AAC7B,IAAA,IAAI,UAAA,GAAoC,QAAA;AACxC,IAAA,IAAI,OAAA,GAGW,OAAO,UAAW,CAAA;AAEjC,IAAA,IAAI,SAAA,GAAY,CAAA;AAChB,IAAA,GAAG;AACD,MAAA,MAAM,OAAA,GAAyB,OAAO,UAAW,CAAA;AACjD,MAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,IAAA,KAAS,KAAA,EAAO;AAExC,MAAA,OAAA,GAAU,OAAA;AACV,MAAA,UAAA,GAAa,MAAA;AACb,MAAA,IACE,CAAC,QAAQ,UAAA,CAAW,UAAA;AAAA,QAClB,IAAI,KAAA,CAAM,SAAA,EAAW,SAAA,GAAY,OAAA,CAAQ,WAAW,MAAM;AAAA,OAC5D;AAIA,QAAA,OAAO,EAAC;AACV,MAAA,SAAA,IAAa,QAAQ,UAAA,CAAW,MAAA;AAChC,MAAA,IAAA,CACG,OAAA,CAAQ,SAAS,cAAA,IAChB,OAAA,CAAQ,SAAS,gBAAA,KACnB,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EACpB;AACA,QAAA,UAAA,GAAa,OAAA,CAAQ,KAAA;AACrB,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,cAAc,OAAA,EAAS;AACzB,QAAA,MAAM,SAAuC,MAAA,CAAO,OAAA;AAAA,UAClD,OAAA,CAAQ;AAAA,SACV,CAAE,KAAK,CAAC,GAAG,IAAI,CAAA,KAAM,MAAA,CAAO,IAAI,CAAC,CAAA;AAEjC,QAAA,IAAI,MAAA,EAAQ;AAEV,UAAA,IAAI,OAAO,CAAC,CAAA,KAAM,IAAI,SAAA,EAAW,CAAA,SAAU,EAAC;AAC5C,UAAA,UAAA,GAAa,OAAO,CAAC,CAAA;AAAA,QACvB;AAAA,MACF;AAAA,IACF,CAAA,QAAS,UAAA;AAET,IAAA,OAAO,CAAC,QAAS,IAAI,CAAA;AAAA,EACvB,CAAC;AACH;;;;"}