@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.
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/esm/index.mjs +12 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/legacy/downstream/archive.mjs +96 -0
- package/dist/esm/legacy/downstream/archive.mjs.map +1 -0
- package/dist/esm/legacy/downstream/chain-head.mjs +214 -0
- package/dist/esm/legacy/downstream/chain-head.mjs.map +1 -0
- package/dist/esm/legacy/downstream/chainspec.mjs +18 -0
- package/dist/esm/legacy/downstream/chainspec.mjs.map +1 -0
- package/dist/esm/legacy/downstream/downstream.mjs +107 -0
- package/dist/esm/legacy/downstream/downstream.mjs.map +1 -0
- package/dist/esm/legacy/downstream/storage.mjs +57 -0
- package/dist/esm/legacy/downstream/storage.mjs.map +1 -0
- package/dist/esm/legacy/downstream/transaction.mjs +48 -0
- package/dist/esm/legacy/downstream/transaction.mjs.map +1 -0
- package/dist/esm/legacy/upstream/blocks/blocks.mjs +309 -0
- package/dist/esm/legacy/upstream/blocks/blocks.mjs.map +1 -0
- package/dist/esm/legacy/upstream/blocks/index.mjs +7 -0
- package/dist/esm/legacy/upstream/blocks/index.mjs.map +1 -0
- package/dist/esm/legacy/upstream/blocks/upstream-events.mjs +92 -0
- package/dist/esm/legacy/upstream/blocks/upstream-events.mjs.map +1 -0
- package/dist/esm/legacy/upstream/proofs.mjs +41 -0
- package/dist/esm/legacy/upstream/proofs.mjs.map +1 -0
- package/dist/esm/legacy/upstream/upstream.mjs +108 -0
- package/dist/esm/legacy/upstream/upstream.mjs.map +1 -0
- package/dist/esm/legacy/utils/create-opaque-token.mjs +7 -0
- package/dist/esm/legacy/utils/create-opaque-token.mjs.map +1 -0
- package/dist/esm/legacy/utils/fromShittyHeader.mjs +31 -0
- package/dist/esm/legacy/utils/fromShittyHeader.mjs.map +1 -0
- package/dist/esm/legacy/utils/get-hasher-from-block.mjs +12 -0
- package/dist/esm/legacy/utils/get-hasher-from-block.mjs.map +1 -0
- package/dist/esm/legacy/utils/message-from-error.mjs +8 -0
- package/dist/esm/legacy/utils/message-from-error.mjs.map +1 -0
- package/dist/esm/legacy/utils/share-latest.mjs +9 -0
- package/dist/esm/legacy/utils/share-latest.mjs.map +1 -0
- package/dist/esm/legacy/utils/with-latest-from-bp.mjs +40 -0
- package/dist/esm/legacy/utils/with-latest-from-bp.mjs.map +1 -0
- package/dist/esm/methods-router.mjs +41 -0
- package/dist/esm/methods-router.mjs.map +1 -0
- package/dist/esm/methods.mjs +40 -0
- package/dist/esm/methods.mjs.map +1 -0
- package/dist/esm/middleware.mjs +22 -0
- package/dist/esm/middleware.mjs.map +1 -0
- package/dist/esm/modern/fix-follow.mjs +79 -0
- package/dist/esm/modern/fix-follow.mjs.map +1 -0
- package/dist/esm/modern/fix-premature-blocks.mjs +94 -0
- package/dist/esm/modern/fix-premature-blocks.mjs.map +1 -0
- package/dist/esm/modern/fix-unordered-blocks.mjs +100 -0
- package/dist/esm/modern/fix-unordered-blocks.mjs.map +1 -0
- package/dist/esm/modern/fix-unordered-events.mjs +101 -0
- package/dist/esm/modern/fix-unordered-events.mjs.map +1 -0
- package/dist/esm/modern/modern.mjs +19 -0
- package/dist/esm/modern/modern.mjs.map +1 -0
- package/dist/esm/modern/patch-chainhead-events.mjs +16 -0
- package/dist/esm/modern/patch-chainhead-events.mjs.map +1 -0
- package/dist/esm/modern/unpin-hash.mjs +22 -0
- package/dist/esm/modern/unpin-hash.mjs.map +1 -0
- package/dist/esm/numeric-ids.mjs +37 -0
- package/dist/esm/numeric-ids.mjs.map +1 -0
- package/dist/esm/utils/get-async-middleware.mjs +60 -0
- package/dist/esm/utils/get-async-middleware.mjs.map +1 -0
- package/dist/esm/utils/utils.mjs +11 -0
- package/dist/esm/utils/utils.mjs.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +1706 -0
- package/dist/index.js.map +1 -0
- 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 @@
|
|
|
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;;;;"}
|