@polkadot-api/json-rpc-provider-proxy 0.2.1 → 0.2.3
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/dist/esm/get-proxy.mjs +101 -0
- package/dist/esm/get-proxy.mjs.map +1 -0
- package/dist/esm/get-sync-provider.mjs +33 -84
- package/dist/esm/get-sync-provider.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +118 -171
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/esm/internal-types.mjs +0 -9
- package/dist/esm/internal-types.mjs.map +0 -1
- package/dist/esm/subscription-manager/chainHeadFollow.mjs +0 -57
- package/dist/esm/subscription-manager/chainHeadFollow.mjs.map +0 -1
- package/dist/esm/subscription-manager/subscription-manager.mjs +0 -46
- package/dist/esm/subscription-manager/subscription-manager.mjs.map +0 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { jsonRpcMsg } from './json-rpc-message.mjs';
|
|
2
|
+
|
|
3
|
+
const unfollowMethods = new Set(
|
|
4
|
+
["v1", "unstable"].map((x) => `chainHead_${x}_unfollow`)
|
|
5
|
+
);
|
|
6
|
+
const getProxy = (toConsumer) => {
|
|
7
|
+
let state = {
|
|
8
|
+
type: 1 /* Connecting */,
|
|
9
|
+
pending: []
|
|
10
|
+
};
|
|
11
|
+
const onMsgFromProvider = (msg) => {
|
|
12
|
+
if (state.type === 0 /* Connected */) {
|
|
13
|
+
const parsed = JSON.parse(msg);
|
|
14
|
+
if ("id" in parsed) {
|
|
15
|
+
if (state.onGoingRequests.get(parsed.id)?.type === 0 /* ChainHeadFollow */)
|
|
16
|
+
state.activeChainHeads.add(parsed.result);
|
|
17
|
+
state.onGoingRequests.delete(parsed.id);
|
|
18
|
+
} else {
|
|
19
|
+
const { subscription, result } = parsed.params;
|
|
20
|
+
if (result?.event === "stop")
|
|
21
|
+
state.activeChainHeads.delete(subscription);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (state.type !== 2 /* Done */) toConsumer(msg);
|
|
25
|
+
};
|
|
26
|
+
const send = (msg) => {
|
|
27
|
+
if (state.type === 2 /* Done */) return;
|
|
28
|
+
if (state.type === 1 /* Connecting */) {
|
|
29
|
+
state.pending.push(msg);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const parsed = JSON.parse(msg);
|
|
33
|
+
if (unfollowMethods.has(parsed.method))
|
|
34
|
+
state.activeChainHeads.delete(parsed.params[0]);
|
|
35
|
+
if ("id" in parsed) {
|
|
36
|
+
const { method, id } = parsed;
|
|
37
|
+
const ongoingMsg = method.startsWith("chainHead") ? method.endsWith("follow") ? {
|
|
38
|
+
type: 0 /* ChainHeadFollow */,
|
|
39
|
+
msg
|
|
40
|
+
} : { type: 1 /* ChainHeadOperation */, id } : { type: 2 /* Other */, msg };
|
|
41
|
+
state.onGoingRequests.set(id, ongoingMsg);
|
|
42
|
+
}
|
|
43
|
+
state.connection.send(msg);
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
send,
|
|
47
|
+
disconnect: () => {
|
|
48
|
+
if (state.type === 2 /* Done */) return;
|
|
49
|
+
if (state.type === 0 /* Connected */) state.connection.disconnect();
|
|
50
|
+
state = { type: 2 /* Done */ };
|
|
51
|
+
},
|
|
52
|
+
connect: (cb) => {
|
|
53
|
+
if (state.type !== 1 /* Connecting */) throw new Error("Nonesense");
|
|
54
|
+
const { pending } = state;
|
|
55
|
+
const onGoingRequests = /* @__PURE__ */ new Map();
|
|
56
|
+
const activeChainHeads = /* @__PURE__ */ new Set();
|
|
57
|
+
const onHalt = () => {
|
|
58
|
+
state = {
|
|
59
|
+
type: 1 /* Connecting */,
|
|
60
|
+
pending: []
|
|
61
|
+
};
|
|
62
|
+
activeChainHeads.forEach((subscription) => {
|
|
63
|
+
onMsgFromProvider(
|
|
64
|
+
jsonRpcMsg({
|
|
65
|
+
params: {
|
|
66
|
+
subscription,
|
|
67
|
+
result: {
|
|
68
|
+
event: "stop",
|
|
69
|
+
internal: true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
activeChainHeads.clear();
|
|
76
|
+
for (const x of onGoingRequests.values()) {
|
|
77
|
+
if (x.type === 1 /* ChainHeadOperation */)
|
|
78
|
+
onMsgFromProvider(
|
|
79
|
+
jsonRpcMsg({
|
|
80
|
+
id: x.id,
|
|
81
|
+
error: { code: -32603, message: "Internal error" },
|
|
82
|
+
internal: true
|
|
83
|
+
})
|
|
84
|
+
);
|
|
85
|
+
else send(x.msg);
|
|
86
|
+
}
|
|
87
|
+
onGoingRequests.clear();
|
|
88
|
+
};
|
|
89
|
+
state = {
|
|
90
|
+
type: 0 /* Connected */,
|
|
91
|
+
connection: cb(onMsgFromProvider, onHalt),
|
|
92
|
+
onGoingRequests,
|
|
93
|
+
activeChainHeads
|
|
94
|
+
};
|
|
95
|
+
pending.forEach(send);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export { getProxy };
|
|
101
|
+
//# sourceMappingURL=get-proxy.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-proxy.mjs","sources":["../../src/get-proxy.ts"],"sourcesContent":["import { JsonRpcConnection } from \"@polkadot-api/json-rpc-provider\"\nimport { ReconnectableJsonRpcConnection } from \"./internal-types\"\nimport { jsonRpcMsg } from \"./json-rpc-message\"\n\nconst enum State {\n Connected,\n Connecting,\n Done,\n}\n\nconst enum OngoingMsgType {\n ChainHeadFollow,\n ChainHeadOperation,\n Other,\n}\ntype OngoingMsg =\n | {\n type: OngoingMsgType.ChainHeadFollow\n msg: string\n }\n | { type: OngoingMsgType.ChainHeadOperation; id: string }\n | { type: OngoingMsgType.Other; msg: string }\n\nconst unfollowMethods = new Set(\n [\"v1\", \"unstable\"].map((x) => `chainHead_${x}_unfollow`),\n)\n\nexport const getProxy: ReconnectableJsonRpcConnection = (\n toConsumer: (msg: string) => void,\n) => {\n let state:\n | {\n type: State.Connected\n connection: JsonRpcConnection\n onGoingRequests: Map<string, OngoingMsg>\n activeChainHeads: Set<string>\n }\n | { type: State.Connecting; pending: Array<string> }\n | { type: State.Done } = {\n type: State.Connecting,\n pending: [],\n }\n\n const onMsgFromProvider = (msg: string) => {\n if (state.type === State.Connected) {\n const parsed = JSON.parse(msg)\n if (\"id\" in parsed) {\n if (\n state.onGoingRequests.get(parsed.id)?.type ===\n OngoingMsgType.ChainHeadFollow\n )\n state.activeChainHeads.add(parsed.result)\n state.onGoingRequests.delete(parsed.id)\n } else {\n const { subscription, result } = parsed.params\n if (result?.event === \"stop\")\n state.activeChainHeads.delete(subscription)\n }\n }\n // If the state is \"Connecting\", then these are messages\n // sent from the `onHalt` function. So, we mus realy them\n if (state.type !== State.Done) toConsumer(msg)\n }\n\n const send = (msg: string) => {\n if (state.type === State.Done) return\n if (state.type === State.Connecting) {\n state.pending.push(msg)\n return\n }\n const parsed = JSON.parse(msg)\n if (unfollowMethods.has(parsed.method))\n state.activeChainHeads.delete(parsed.params[0])\n\n if (\"id\" in parsed) {\n const { method, id } = parsed as { method: string; id: string }\n const ongoingMsg: OngoingMsg = method.startsWith(\"chainHead\")\n ? method.endsWith(\"follow\")\n ? {\n type: OngoingMsgType.ChainHeadFollow,\n msg,\n }\n : { type: OngoingMsgType.ChainHeadOperation, id }\n : { type: OngoingMsgType.Other, msg }\n state.onGoingRequests.set(id, ongoingMsg)\n }\n\n state.connection.send(msg)\n }\n\n return {\n send,\n disconnect: () => {\n if (state.type === State.Done) return\n if (state.type === State.Connected) state.connection.disconnect()\n state = { type: State.Done }\n },\n connect: (cb) => {\n if (state.type !== State.Connecting) throw new Error(\"Nonesense\")\n\n const { pending } = state\n const onGoingRequests = new Map<string, OngoingMsg>()\n const activeChainHeads = new Set<string>()\n const onHalt = () => {\n state = {\n type: State.Connecting,\n pending: [],\n }\n activeChainHeads.forEach((subscription) => {\n // We don't send the messages directy to the consumer\n // b/c they could have disconnected after receiving one\n // of these messages. The `onMsgFromProvider` fn handles that\n onMsgFromProvider(\n jsonRpcMsg({\n params: {\n subscription,\n result: {\n event: \"stop\",\n internal: true,\n },\n },\n }),\n )\n })\n activeChainHeads.clear()\n for (const x of onGoingRequests.values()) {\n if (x.type === OngoingMsgType.ChainHeadOperation)\n onMsgFromProvider(\n jsonRpcMsg({\n id: x.id,\n error: { code: -32603, message: \"Internal error\" },\n internal: true,\n }),\n )\n else send(x.msg)\n }\n onGoingRequests.clear()\n }\n state = {\n type: State.Connected,\n connection: cb(onMsgFromProvider, onHalt),\n onGoingRequests,\n activeChainHeads,\n }\n pending.forEach(send)\n },\n }\n}\n"],"names":[],"mappings":";;AAuBA,MAAM,kBAAkB,IAAI,GAAA;AAAA,EAC1B,CAAC,MAAM,UAAU,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,CAAa,UAAA,EAAA,CAAC,CAAW,SAAA,CAAA,CAAA;AACzD,CAAA,CAAA;AAEa,MAAA,QAAA,GAA2C,CACtD,UACG,KAAA;AACH,EAAA,IAAI,KAQuB,GAAA;AAAA,IACzB,IAAM,EAAA,CAAA;AAAA,IACN,SAAS,EAAC;AAAA,GACZ,CAAA;AAEA,EAAM,MAAA,iBAAA,GAAoB,CAAC,GAAgB,KAAA;AACzC,IAAI,IAAA,KAAA,CAAM,SAAS,CAAiB,kBAAA;AAClC,MAAM,MAAA,MAAA,GAAS,IAAK,CAAA,KAAA,CAAM,GAAG,CAAA,CAAA;AAC7B,MAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,QAAA,IACE,MAAM,eAAgB,CAAA,GAAA,CAAI,MAAO,CAAA,EAAE,GAAG,IACtC,KAAA,CAAA;AAEA,UAAM,KAAA,CAAA,gBAAA,CAAiB,GAAI,CAAA,MAAA,CAAO,MAAM,CAAA,CAAA;AAC1C,QAAM,KAAA,CAAA,eAAA,CAAgB,MAAO,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAAA,OACjC,MAAA;AACL,QAAA,MAAM,EAAE,YAAA,EAAc,MAAO,EAAA,GAAI,MAAO,CAAA,MAAA,CAAA;AACxC,QAAA,IAAI,QAAQ,KAAU,KAAA,MAAA;AACpB,UAAM,KAAA,CAAA,gBAAA,CAAiB,OAAO,YAAY,CAAA,CAAA;AAAA,OAC9C;AAAA,KACF;AAGA,IAAA,IAAI,KAAM,CAAA,IAAA,KAAS,CAAY,aAAA,UAAA,CAAW,GAAG,CAAA,CAAA;AAAA,GAC/C,CAAA;AAEA,EAAM,MAAA,IAAA,GAAO,CAAC,GAAgB,KAAA;AAC5B,IAAI,IAAA,KAAA,CAAM,SAAS,CAAY,aAAA,OAAA;AAC/B,IAAI,IAAA,KAAA,CAAM,SAAS,CAAkB,mBAAA;AACnC,MAAM,KAAA,CAAA,OAAA,CAAQ,KAAK,GAAG,CAAA,CAAA;AACtB,MAAA,OAAA;AAAA,KACF;AACA,IAAM,MAAA,MAAA,GAAS,IAAK,CAAA,KAAA,CAAM,GAAG,CAAA,CAAA;AAC7B,IAAI,IAAA,eAAA,CAAgB,GAAI,CAAA,MAAA,CAAO,MAAM,CAAA;AACnC,MAAA,KAAA,CAAM,gBAAiB,CAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA;AAEhD,IAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,MAAM,MAAA,EAAE,MAAQ,EAAA,EAAA,EAAO,GAAA,MAAA,CAAA;AACvB,MAAM,MAAA,UAAA,GAAyB,OAAO,UAAW,CAAA,WAAW,IACxD,MAAO,CAAA,QAAA,CAAS,QAAQ,CACtB,GAAA;AAAA,QACE,IAAM,EAAA,CAAA;AAAA,QACN,GAAA;AAAA,OACF,GACA,EAAE,IAAM,EAAA,CAAA,2BAAmC,IAC7C,GAAA,EAAE,IAAM,EAAA,CAAA,cAAsB,GAAI,EAAA,CAAA;AACtC,MAAM,KAAA,CAAA,eAAA,CAAgB,GAAI,CAAA,EAAA,EAAI,UAAU,CAAA,CAAA;AAAA,KAC1C;AAEA,IAAM,KAAA,CAAA,UAAA,CAAW,KAAK,GAAG,CAAA,CAAA;AAAA,GAC3B,CAAA;AAEA,EAAO,OAAA;AAAA,IACL,IAAA;AAAA,IACA,YAAY,MAAM;AAChB,MAAI,IAAA,KAAA,CAAM,SAAS,CAAY,aAAA,OAAA;AAC/B,MAAA,IAAI,KAAM,CAAA,IAAA,KAAS,CAAiB,kBAAA,KAAA,CAAM,WAAW,UAAW,EAAA,CAAA;AAChE,MAAQ,KAAA,GAAA,EAAE,MAAM,CAAW,aAAA,CAAA;AAAA,KAC7B;AAAA,IACA,OAAA,EAAS,CAAC,EAAO,KAAA;AACf,MAAA,IAAI,MAAM,IAAS,KAAA,CAAA,mBAAwB,MAAA,IAAI,MAAM,WAAW,CAAA,CAAA;AAEhE,MAAM,MAAA,EAAE,SAAY,GAAA,KAAA,CAAA;AACpB,MAAM,MAAA,eAAA,uBAAsB,GAAwB,EAAA,CAAA;AACpD,MAAM,MAAA,gBAAA,uBAAuB,GAAY,EAAA,CAAA;AACzC,MAAA,MAAM,SAAS,MAAM;AACnB,QAAQ,KAAA,GAAA;AAAA,UACN,IAAM,EAAA,CAAA;AAAA,UACN,SAAS,EAAC;AAAA,SACZ,CAAA;AACA,QAAiB,gBAAA,CAAA,OAAA,CAAQ,CAAC,YAAiB,KAAA;AAIzC,UAAA,iBAAA;AAAA,YACE,UAAW,CAAA;AAAA,cACT,MAAQ,EAAA;AAAA,gBACN,YAAA;AAAA,gBACA,MAAQ,EAAA;AAAA,kBACN,KAAO,EAAA,MAAA;AAAA,kBACP,QAAU,EAAA,IAAA;AAAA,iBACZ;AAAA,eACF;AAAA,aACD,CAAA;AAAA,WACH,CAAA;AAAA,SACD,CAAA,CAAA;AACD,QAAA,gBAAA,CAAiB,KAAM,EAAA,CAAA;AACvB,QAAW,KAAA,MAAA,CAAA,IAAK,eAAgB,CAAA,MAAA,EAAU,EAAA;AACxC,UAAA,IAAI,EAAE,IAAS,KAAA,CAAA;AACb,YAAA,iBAAA;AAAA,cACE,UAAW,CAAA;AAAA,gBACT,IAAI,CAAE,CAAA,EAAA;AAAA,gBACN,KAAO,EAAA,EAAE,IAAM,EAAA,CAAA,KAAA,EAAQ,SAAS,gBAAiB,EAAA;AAAA,gBACjD,QAAU,EAAA,IAAA;AAAA,eACX,CAAA;AAAA,aACH,CAAA;AAAA,eACG,IAAA,CAAK,EAAE,GAAG,CAAA,CAAA;AAAA,SACjB;AACA,QAAA,eAAA,CAAgB,KAAM,EAAA,CAAA;AAAA,OACxB,CAAA;AACA,MAAQ,KAAA,GAAA;AAAA,QACN,IAAM,EAAA,CAAA;AAAA,QACN,UAAA,EAAY,EAAG,CAAA,iBAAA,EAAmB,MAAM,CAAA;AAAA,QACxC,eAAA;AAAA,QACA,gBAAA;AAAA,OACF,CAAA;AACA,MAAA,OAAA,CAAQ,QAAQ,IAAI,CAAA,CAAA;AAAA,KACtB;AAAA,GACF,CAAA;AACF;;;;"}
|
|
@@ -1,95 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { jsonRpcMsg } from './json-rpc-message.mjs';
|
|
1
|
+
import { getProxy } from './get-proxy.mjs';
|
|
3
2
|
|
|
4
3
|
const getSyncProvider = (input) => (onMessage) => {
|
|
5
|
-
let
|
|
6
|
-
let bufferedMessages = [];
|
|
7
|
-
const pendingResponses = /* @__PURE__ */ new Set();
|
|
8
|
-
const subscriptionManager = getSubscriptionManager(onMessage);
|
|
9
|
-
const onMessageProxy = (message) => {
|
|
10
|
-
let parsed;
|
|
11
|
-
try {
|
|
12
|
-
parsed = JSON.parse(message);
|
|
13
|
-
} catch (_) {
|
|
14
|
-
console.error(`Unable to parse incoming message: ${message}`);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
if (parsed.id !== void 0) {
|
|
18
|
-
pendingResponses.delete(parsed.id);
|
|
19
|
-
subscriptionManager.onResponse(parsed);
|
|
20
|
-
} else {
|
|
21
|
-
subscriptionManager.onNotifiaction(parsed);
|
|
22
|
-
}
|
|
23
|
-
onMessage(message);
|
|
24
|
-
};
|
|
25
|
-
const send = (message) => {
|
|
26
|
-
if (!provider) return;
|
|
27
|
-
const parsed = JSON.parse(message);
|
|
28
|
-
subscriptionManager.onSent(parsed);
|
|
29
|
-
if (parsed.id) pendingResponses.add(parsed.id);
|
|
30
|
-
if (provider instanceof Promise) {
|
|
31
|
-
bufferedMessages.push(message);
|
|
32
|
-
} else provider.send(message);
|
|
33
|
-
};
|
|
34
|
-
const onHalt = () => {
|
|
35
|
-
bufferedMessages = [];
|
|
36
|
-
const pendingResponsesCopy = [...pendingResponses];
|
|
37
|
-
pendingResponses.clear();
|
|
38
|
-
if (!provider) throw null;
|
|
39
|
-
const result = start();
|
|
40
|
-
subscriptionManager.onAbort();
|
|
41
|
-
pendingResponsesCopy.forEach((id) => {
|
|
42
|
-
onMessage(
|
|
43
|
-
jsonRpcMsg({
|
|
44
|
-
error: { code: -32603, message: "Internal error" },
|
|
45
|
-
id
|
|
46
|
-
})
|
|
47
|
-
);
|
|
48
|
-
});
|
|
49
|
-
return result;
|
|
50
|
-
};
|
|
4
|
+
let proxy = getProxy(onMessage);
|
|
51
5
|
const start = () => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
subscriptionManager.onDisconnect();
|
|
77
|
-
pendingResponses.clear();
|
|
78
|
-
provider = null;
|
|
79
|
-
input2?.disconnect();
|
|
80
|
-
};
|
|
81
|
-
if (provider instanceof Promise) {
|
|
82
|
-
provider.then(finishIt, finishIt);
|
|
83
|
-
provider = null;
|
|
84
|
-
} else finishIt(provider);
|
|
6
|
+
input().then(
|
|
7
|
+
(cb) => {
|
|
8
|
+
if (!proxy) {
|
|
9
|
+
try {
|
|
10
|
+
cb(
|
|
11
|
+
() => {
|
|
12
|
+
},
|
|
13
|
+
() => {
|
|
14
|
+
}
|
|
15
|
+
).disconnect();
|
|
16
|
+
} catch (_) {
|
|
17
|
+
}
|
|
18
|
+
} else
|
|
19
|
+
proxy.connect(
|
|
20
|
+
(onMsg, onHalt) => cb(onMsg, () => {
|
|
21
|
+
onHalt();
|
|
22
|
+
start();
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
() => {
|
|
27
|
+
proxy && setTimeout(start, 0);
|
|
28
|
+
}
|
|
29
|
+
);
|
|
85
30
|
};
|
|
86
31
|
start();
|
|
87
32
|
return {
|
|
88
|
-
send
|
|
89
|
-
|
|
33
|
+
send: (msg) => {
|
|
34
|
+
proxy?.send(msg);
|
|
35
|
+
},
|
|
36
|
+
disconnect: () => {
|
|
37
|
+
proxy?.disconnect();
|
|
38
|
+
proxy = null;
|
|
39
|
+
}
|
|
90
40
|
};
|
|
91
41
|
};
|
|
92
|
-
const withMacroTask = (inputFn) => (...args) => new Promise((res) => setTimeout(res, 0)).then(() => inputFn(...args));
|
|
93
42
|
|
|
94
43
|
export { getSyncProvider };
|
|
95
44
|
//# sourceMappingURL=get-sync-provider.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-sync-provider.mjs","sources":["../../src/get-sync-provider.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"get-sync-provider.mjs","sources":["../../src/get-sync-provider.ts"],"sourcesContent":["import type { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\nimport { getProxy } from \"./get-proxy\"\nimport { AsyncJsonRpcProvider } from \"./public-types\"\nimport { ConnectableJsonRpcConnection } from \"./internal-types\"\n\nexport const getSyncProvider =\n (input: () => Promise<AsyncJsonRpcProvider>): JsonRpcProvider =>\n (onMessage) => {\n let proxy: ConnectableJsonRpcConnection | null = getProxy(onMessage)\n\n const start = () => {\n input().then(\n (cb) => {\n if (!proxy) {\n try {\n cb(\n () => {},\n () => {},\n ).disconnect()\n } catch (_) {}\n } else\n proxy.connect((onMsg, onHalt) =>\n cb(onMsg, () => {\n onHalt()\n start()\n }),\n )\n },\n () => {\n proxy && setTimeout(start, 0)\n },\n )\n }\n\n start()\n return {\n send: (msg) => {\n proxy?.send(msg)\n },\n disconnect: () => {\n proxy?.disconnect()\n proxy = null\n },\n }\n }\n"],"names":[],"mappings":";;AAKO,MAAM,eACX,GAAA,CAAC,KACD,KAAA,CAAC,SAAc,KAAA;AACb,EAAI,IAAA,KAAA,GAA6C,SAAS,SAAS,CAAA,CAAA;AAEnE,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,KAAA,EAAQ,CAAA,IAAA;AAAA,MACN,CAAC,EAAO,KAAA;AACN,QAAA,IAAI,CAAC,KAAO,EAAA;AACV,UAAI,IAAA;AACF,YAAA,EAAA;AAAA,cACE,MAAM;AAAA,eAAC;AAAA,cACP,MAAM;AAAA,eAAC;AAAA,cACP,UAAW,EAAA,CAAA;AAAA,mBACN,CAAG,EAAA;AAAA,WAAC;AAAA,SACf;AACE,UAAM,KAAA,CAAA,OAAA;AAAA,YAAQ,CAAC,KAAA,EAAO,MACpB,KAAA,EAAA,CAAG,OAAO,MAAM;AACd,cAAO,MAAA,EAAA,CAAA;AACP,cAAM,KAAA,EAAA,CAAA;AAAA,aACP,CAAA;AAAA,WACH,CAAA;AAAA,OACJ;AAAA,MACA,MAAM;AACJ,QAAS,KAAA,IAAA,UAAA,CAAW,OAAO,CAAC,CAAA,CAAA;AAAA,OAC9B;AAAA,KACF,CAAA;AAAA,GACF,CAAA;AAEA,EAAM,KAAA,EAAA,CAAA;AACN,EAAO,OAAA;AAAA,IACL,IAAA,EAAM,CAAC,GAAQ,KAAA;AACb,MAAA,KAAA,EAAO,KAAK,GAAG,CAAA,CAAA;AAAA,KACjB;AAAA,IACA,YAAY,MAAM;AAChB,MAAA,KAAA,EAAO,UAAW,EAAA,CAAA;AAClB,MAAQ,KAAA,GAAA,IAAA,CAAA;AAAA,KACV;AAAA,GACF,CAAA;AACF;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { JsonRpcConnection, JsonRpcProvider } from '@polkadot-api/json-rpc-provider';
|
|
2
2
|
|
|
3
3
|
type AsyncJsonRpcProvider = (onMessage: (message: string) => void, onHalt: () => void) => JsonRpcConnection;
|
|
4
|
+
|
|
4
5
|
declare const getSyncProvider: (input: () => Promise<AsyncJsonRpcProvider>) => JsonRpcProvider;
|
|
5
6
|
|
|
6
7
|
export { type AsyncJsonRpcProvider, getSyncProvider };
|
package/dist/index.js
CHANGED
|
@@ -1,199 +1,146 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
4
|
-
MessageType2[MessageType2["subscribe"] = 0] = "subscribe";
|
|
5
|
-
MessageType2[MessageType2["unsubscribe"] = 1] = "unsubscribe";
|
|
6
|
-
MessageType2[MessageType2["end"] = 2] = "end";
|
|
7
|
-
return MessageType2;
|
|
8
|
-
})(MessageType || {});
|
|
9
|
-
|
|
10
3
|
const jsonRpcMsg = (msg) => JSON.stringify({
|
|
11
4
|
jsonrpc: "2.0",
|
|
12
5
|
...msg
|
|
13
6
|
});
|
|
14
7
|
|
|
15
|
-
const
|
|
16
|
-
"
|
|
17
|
-
"unfollow",
|
|
18
|
-
"followEvent"
|
|
19
|
-
].map(
|
|
20
|
-
(name) => new Set(
|
|
21
|
-
["v1", "unstable"].map((version) => `chainHead_${version}_${name}`)
|
|
22
|
-
)
|
|
8
|
+
const unfollowMethods = new Set(
|
|
9
|
+
["v1", "unstable"].map((x) => `chainHead_${x}_unfollow`)
|
|
23
10
|
);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
onSent(parsed) {
|
|
29
|
-
if (START_METHODS.has(parsed.method)) {
|
|
30
|
-
notificationMethod = parsed.method + "Event";
|
|
31
|
-
return {
|
|
32
|
-
type: MessageType.subscribe,
|
|
33
|
-
id: parsed.id,
|
|
34
|
-
onRes: (innerParsed) => innerParsed.id === parsed.id ? { id: innerParsed.result } : null
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
if (STOP_METHODS.has(parsed.method))
|
|
38
|
-
return {
|
|
39
|
-
type: MessageType.unsubscribe,
|
|
40
|
-
id: Object.values(parsed.params)[0]
|
|
41
|
-
};
|
|
42
|
-
return null;
|
|
43
|
-
},
|
|
44
|
-
onNotification(parsed) {
|
|
45
|
-
return NOTIFICATION_METHODS.has(parsed.method) && parsed.params.result.event === STOP_EVENT ? {
|
|
46
|
-
type: MessageType.end,
|
|
47
|
-
id: parsed.params.subscription
|
|
48
|
-
} : null;
|
|
49
|
-
},
|
|
50
|
-
onAbort: (id) => {
|
|
51
|
-
onMessage(
|
|
52
|
-
jsonRpcMsg({
|
|
53
|
-
method: notificationMethod,
|
|
54
|
-
params: {
|
|
55
|
-
subscription: id,
|
|
56
|
-
result: {
|
|
57
|
-
event: STOP_EVENT,
|
|
58
|
-
eventType: "internal"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
);
|
|
63
|
-
}
|
|
11
|
+
const getProxy = (toConsumer) => {
|
|
12
|
+
let state = {
|
|
13
|
+
type: 1 /* Connecting */,
|
|
14
|
+
pending: []
|
|
64
15
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
active.clear();
|
|
77
|
-
};
|
|
78
|
-
return {
|
|
79
|
-
onSent(parsed) {
|
|
80
|
-
const result = onSent(parsed);
|
|
81
|
-
if (result) {
|
|
82
|
-
if (result.type === MessageType.subscribe)
|
|
83
|
-
preActive.set(result.id, result.onRes);
|
|
84
|
-
else active.delete(result.id);
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
onResponse(parsed) {
|
|
88
|
-
const match = preActive.get(parsed.id)?.(parsed);
|
|
89
|
-
if (match) {
|
|
90
|
-
preActive.delete(parsed.id);
|
|
91
|
-
active.add(match.id);
|
|
16
|
+
const onMsgFromProvider = (msg) => {
|
|
17
|
+
if (state.type === 0 /* Connected */) {
|
|
18
|
+
const parsed = JSON.parse(msg);
|
|
19
|
+
if ("id" in parsed) {
|
|
20
|
+
if (state.onGoingRequests.get(parsed.id)?.type === 0 /* ChainHeadFollow */)
|
|
21
|
+
state.activeChainHeads.add(parsed.result);
|
|
22
|
+
state.onGoingRequests.delete(parsed.id);
|
|
23
|
+
} else {
|
|
24
|
+
const { subscription, result } = parsed.params;
|
|
25
|
+
if (result?.event === "stop")
|
|
26
|
+
state.activeChainHeads.delete(subscription);
|
|
92
27
|
}
|
|
93
|
-
},
|
|
94
|
-
onNotifiaction(parsed) {
|
|
95
|
-
const result = onNotification(parsed);
|
|
96
|
-
if (result) active.delete(result.id);
|
|
97
|
-
},
|
|
98
|
-
onDisconnect,
|
|
99
|
-
onAbort() {
|
|
100
|
-
const activeCopy = [...active];
|
|
101
|
-
onDisconnect();
|
|
102
|
-
activeCopy.forEach(onAbort);
|
|
103
28
|
}
|
|
29
|
+
if (state.type !== 2 /* Done */) toConsumer(msg);
|
|
104
30
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
let provider;
|
|
110
|
-
let bufferedMessages = [];
|
|
111
|
-
const pendingResponses = /* @__PURE__ */ new Set();
|
|
112
|
-
const subscriptionManager = getSubscriptionManager(onMessage);
|
|
113
|
-
const onMessageProxy = (message) => {
|
|
114
|
-
let parsed;
|
|
115
|
-
try {
|
|
116
|
-
parsed = JSON.parse(message);
|
|
117
|
-
} catch (_) {
|
|
118
|
-
console.error(`Unable to parse incoming message: ${message}`);
|
|
31
|
+
const send = (msg) => {
|
|
32
|
+
if (state.type === 2 /* Done */) return;
|
|
33
|
+
if (state.type === 1 /* Connecting */) {
|
|
34
|
+
state.pending.push(msg);
|
|
119
35
|
return;
|
|
120
36
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
37
|
+
const parsed = JSON.parse(msg);
|
|
38
|
+
if (unfollowMethods.has(parsed.method))
|
|
39
|
+
state.activeChainHeads.delete(parsed.params[0]);
|
|
40
|
+
if ("id" in parsed) {
|
|
41
|
+
const { method, id } = parsed;
|
|
42
|
+
const ongoingMsg = method.startsWith("chainHead") ? method.endsWith("follow") ? {
|
|
43
|
+
type: 0 /* ChainHeadFollow */,
|
|
44
|
+
msg
|
|
45
|
+
} : { type: 1 /* ChainHeadOperation */, id } : { type: 2 /* Other */, msg };
|
|
46
|
+
state.onGoingRequests.set(id, ongoingMsg);
|
|
126
47
|
}
|
|
127
|
-
|
|
128
|
-
};
|
|
129
|
-
const send = (message) => {
|
|
130
|
-
if (!provider) return;
|
|
131
|
-
const parsed = JSON.parse(message);
|
|
132
|
-
subscriptionManager.onSent(parsed);
|
|
133
|
-
if (parsed.id) pendingResponses.add(parsed.id);
|
|
134
|
-
if (provider instanceof Promise) {
|
|
135
|
-
bufferedMessages.push(message);
|
|
136
|
-
} else provider.send(message);
|
|
137
|
-
};
|
|
138
|
-
const onHalt = () => {
|
|
139
|
-
bufferedMessages = [];
|
|
140
|
-
const pendingResponsesCopy = [...pendingResponses];
|
|
141
|
-
pendingResponses.clear();
|
|
142
|
-
if (!provider) throw null;
|
|
143
|
-
const result = start();
|
|
144
|
-
subscriptionManager.onAbort();
|
|
145
|
-
pendingResponsesCopy.forEach((id) => {
|
|
146
|
-
onMessage(
|
|
147
|
-
jsonRpcMsg({
|
|
148
|
-
error: { code: -32603, message: "Internal error" },
|
|
149
|
-
id
|
|
150
|
-
})
|
|
151
|
-
);
|
|
152
|
-
});
|
|
153
|
-
return result;
|
|
48
|
+
state.connection.send(msg);
|
|
154
49
|
};
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
50
|
+
return {
|
|
51
|
+
send,
|
|
52
|
+
disconnect: () => {
|
|
53
|
+
if (state.type === 2 /* Done */) return;
|
|
54
|
+
if (state.type === 0 /* Connected */) state.connection.disconnect();
|
|
55
|
+
state = { type: 2 /* Done */ };
|
|
56
|
+
},
|
|
57
|
+
connect: (cb) => {
|
|
58
|
+
if (state.type !== 1 /* Connecting */) throw new Error("Nonesense");
|
|
59
|
+
const { pending } = state;
|
|
60
|
+
const onGoingRequests = /* @__PURE__ */ new Map();
|
|
61
|
+
const activeChainHeads = /* @__PURE__ */ new Set();
|
|
62
|
+
const onHalt = () => {
|
|
63
|
+
state = {
|
|
64
|
+
type: 1 /* Connecting */,
|
|
65
|
+
pending: []
|
|
66
|
+
};
|
|
67
|
+
activeChainHeads.forEach((subscription) => {
|
|
68
|
+
onMsgFromProvider(
|
|
69
|
+
jsonRpcMsg({
|
|
70
|
+
params: {
|
|
71
|
+
subscription,
|
|
72
|
+
result: {
|
|
73
|
+
event: "stop",
|
|
74
|
+
internal: true
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
activeChainHeads.clear();
|
|
81
|
+
for (const x of onGoingRequests.values()) {
|
|
82
|
+
if (x.type === 1 /* ChainHeadOperation */)
|
|
83
|
+
onMsgFromProvider(
|
|
84
|
+
jsonRpcMsg({
|
|
85
|
+
id: x.id,
|
|
86
|
+
error: { code: -32603, message: "Internal error" },
|
|
87
|
+
internal: true
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
else send(x.msg);
|
|
162
91
|
}
|
|
92
|
+
onGoingRequests.clear();
|
|
163
93
|
};
|
|
164
|
-
|
|
165
|
-
|
|
94
|
+
state = {
|
|
95
|
+
type: 0 /* Connected */,
|
|
96
|
+
connection: cb(onMsgFromProvider, onHalt),
|
|
97
|
+
onGoingRequests,
|
|
98
|
+
activeChainHeads
|
|
166
99
|
};
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
result.send(m);
|
|
170
|
-
});
|
|
171
|
-
bufferedMessages = [];
|
|
172
|
-
return provider = result;
|
|
173
|
-
};
|
|
174
|
-
provider = input().then(onResolve, withMacroTask(onHalt));
|
|
175
|
-
return provider;
|
|
100
|
+
pending.forEach(send);
|
|
101
|
+
}
|
|
176
102
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const getSyncProvider = (input) => (onMessage) => {
|
|
106
|
+
let proxy = getProxy(onMessage);
|
|
107
|
+
const start = () => {
|
|
108
|
+
input().then(
|
|
109
|
+
(cb) => {
|
|
110
|
+
if (!proxy) {
|
|
111
|
+
try {
|
|
112
|
+
cb(
|
|
113
|
+
() => {
|
|
114
|
+
},
|
|
115
|
+
() => {
|
|
116
|
+
}
|
|
117
|
+
).disconnect();
|
|
118
|
+
} catch (_) {
|
|
119
|
+
}
|
|
120
|
+
} else
|
|
121
|
+
proxy.connect(
|
|
122
|
+
(onMsg, onHalt) => cb(onMsg, () => {
|
|
123
|
+
onHalt();
|
|
124
|
+
start();
|
|
125
|
+
})
|
|
126
|
+
);
|
|
127
|
+
},
|
|
128
|
+
() => {
|
|
129
|
+
proxy && setTimeout(start, 0);
|
|
130
|
+
}
|
|
131
|
+
);
|
|
189
132
|
};
|
|
190
133
|
start();
|
|
191
134
|
return {
|
|
192
|
-
send
|
|
193
|
-
|
|
135
|
+
send: (msg) => {
|
|
136
|
+
proxy?.send(msg);
|
|
137
|
+
},
|
|
138
|
+
disconnect: () => {
|
|
139
|
+
proxy?.disconnect();
|
|
140
|
+
proxy = null;
|
|
141
|
+
}
|
|
194
142
|
};
|
|
195
143
|
};
|
|
196
|
-
const withMacroTask = (inputFn) => (...args) => new Promise((res) => setTimeout(res, 0)).then(() => inputFn(...args));
|
|
197
144
|
|
|
198
145
|
exports.getSyncProvider = getSyncProvider;
|
|
199
146
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/internal-types.ts","../src/json-rpc-message.ts","../src/subscription-manager/chainHeadFollow.ts","../src/subscription-manager/subscription-manager.ts","../src/get-sync-provider.ts"],"sourcesContent":["export type RequestId = string | number | null\nexport type SubscriptionId = string | number\nexport type JsonMessage = {\n jsonrpc: \"2.0\"\n method: string\n params: {}\n}\n\nexport const enum MessageType {\n subscribe,\n unsubscribe,\n end,\n}\n\nexport interface SubscriptionLogic {\n onSent: (parsed: any) =>\n | {\n type: MessageType.subscribe\n id: RequestId\n onRes: (parsed: any) => { id: SubscriptionId } | null\n }\n | { type: MessageType.unsubscribe; id: SubscriptionId }\n | null\n onNotification: (\n parsed: any,\n ) => { type: MessageType.end; id: SubscriptionId } | null\n onAbort: (id: SubscriptionId) => void\n}\n","export const jsonRpcMsg = <T extends {}>(msg: T) =>\n JSON.stringify({\n jsonrpc: \"2.0\",\n ...msg,\n })\n","import {\n MessageType,\n SubscriptionId,\n SubscriptionLogic,\n} from \"@/internal-types\"\nimport { jsonRpcMsg } from \"@/json-rpc-message\"\n\nconst [START_METHODS, STOP_METHODS, NOTIFICATION_METHODS] = [\n \"follow\",\n \"unfollow\",\n \"followEvent\",\n].map(\n (name) =>\n new Set(\n [\"v1\", \"unstable\"].map((version) => `chainHead_${version}_${name}`),\n ),\n)\nconst STOP_EVENT = \"stop\"\n\nexport const chainHeadFollow = (\n onMessage: (msg: string) => void,\n): SubscriptionLogic => {\n let notificationMethod = \"\"\n return {\n onSent(parsed) {\n if (START_METHODS.has(parsed.method)) {\n notificationMethod = parsed.method + \"Event\"\n return {\n type: MessageType.subscribe,\n id: parsed.id,\n onRes: (innerParsed) =>\n innerParsed.id === parsed.id ? { id: innerParsed.result } : null,\n }\n }\n\n if (STOP_METHODS.has(parsed.method))\n return {\n type: MessageType.unsubscribe,\n id: Object.values(parsed.params)[0] as string,\n }\n\n return null\n },\n onNotification(parsed) {\n return NOTIFICATION_METHODS.has(parsed.method) &&\n parsed.params.result.event === STOP_EVENT\n ? {\n type: MessageType.end,\n id: parsed.params.subscription as SubscriptionId,\n }\n : null\n },\n onAbort: (id) => {\n onMessage(\n jsonRpcMsg({\n method: notificationMethod,\n params: {\n subscription: id,\n result: {\n event: STOP_EVENT,\n eventType: \"internal\",\n },\n },\n }),\n )\n },\n }\n}\n","import {\n MessageType,\n type RequestId,\n type SubscriptionId,\n type SubscriptionLogic,\n} from \"../internal-types\"\nimport { chainHeadFollow } from \"./chainHeadFollow\"\n\nexport const addSubscription = ({\n onSent,\n onNotification,\n onAbort,\n}: SubscriptionLogic) => {\n const preActive = new Map<\n RequestId,\n (parsed: any) => { id: SubscriptionId } | null\n >()\n const active = new Set<SubscriptionId>()\n\n const onDisconnect = () => {\n preActive.clear()\n active.clear()\n }\n\n return {\n onSent(parsed: any) {\n const result = onSent(parsed)\n if (result) {\n if (result.type === MessageType.subscribe)\n preActive.set(result.id, result.onRes)\n else active.delete(result.id)\n }\n },\n onResponse(parsed: any) {\n const match = preActive.get(parsed.id)?.(parsed)\n if (match) {\n preActive.delete(parsed.id)\n active.add(match.id)\n }\n },\n onNotifiaction(parsed: any) {\n const result = onNotification(parsed)\n if (result) active.delete(result.id)\n },\n onDisconnect,\n onAbort() {\n const activeCopy = [...active]\n onDisconnect()\n activeCopy.forEach(onAbort)\n },\n }\n}\n\nexport const getSubscriptionManager = (onMessage: (msg: string) => void) =>\n addSubscription(chainHeadFollow(onMessage))\n","import type { RequestId } from \"./internal-types\"\nimport type {\n JsonRpcProvider,\n JsonRpcConnection,\n} from \"@polkadot-api/json-rpc-provider\"\nimport { getSubscriptionManager } from \"./subscription-manager\"\nimport { jsonRpcMsg } from \"./json-rpc-message\"\n\nexport type AsyncJsonRpcProvider = (\n onMessage: (message: string) => void,\n onHalt: () => void,\n) => JsonRpcConnection\n\nexport const getSyncProvider =\n (input: () => Promise<AsyncJsonRpcProvider>): JsonRpcProvider =>\n (onMessage) => {\n // if it's null it means that the consumer has called `disconnect`\n // of it's a Promise it means that it's being respolved, otherwise it's resolved\n let provider: JsonRpcConnection | Promise<JsonRpcConnection> | null\n\n let bufferedMessages: Array<string> = []\n const pendingResponses = new Set<RequestId>()\n const subscriptionManager = getSubscriptionManager(onMessage)\n\n const onMessageProxy = (message: string) => {\n let parsed: any\n try {\n parsed = JSON.parse(message)\n } catch (_) {\n console.error(`Unable to parse incoming message: ${message}`)\n return\n }\n\n if (parsed.id !== undefined) {\n pendingResponses.delete(parsed.id)\n subscriptionManager.onResponse(parsed)\n } else {\n subscriptionManager.onNotifiaction(parsed)\n }\n\n onMessage(message)\n }\n\n const send = (message: string) => {\n if (!provider) return\n\n const parsed = JSON.parse(message)\n subscriptionManager.onSent(parsed)\n if (parsed.id) pendingResponses.add(parsed.id)\n\n if (provider instanceof Promise) {\n bufferedMessages.push(message)\n } else provider.send(message)\n }\n\n const onHalt = (): Promise<JsonRpcConnection> => {\n bufferedMessages = []\n const pendingResponsesCopy = [...pendingResponses]\n pendingResponses.clear()\n\n // it means that the user has disconnected while the\n // provider promise was being rejected. Therefore, we must\n // throw to prevent the Promise from recovering.\n // The rejection will be handled from the teardown logic.\n if (!provider) throw null\n\n // It needs to restart before sending the errored\n // responses/notifications because the consumer may\n // react to those by sending new requests\n const result = start()\n\n subscriptionManager.onAbort()\n pendingResponsesCopy.forEach((id) => {\n onMessage(\n jsonRpcMsg({\n error: { code: -32603, message: \"Internal error\" },\n id,\n }),\n )\n })\n\n return result\n }\n\n const start = (): Promise<JsonRpcConnection> => {\n const onResolve = (getProvider: AsyncJsonRpcProvider) => {\n let alive = true\n const _onHalt = () => {\n if (alive) {\n alive = false\n onHalt()\n }\n }\n\n const _onMessageProxy = (msg: string) => {\n if (alive) onMessageProxy(msg)\n }\n\n const result = getProvider(_onMessageProxy, _onHalt)\n bufferedMessages.forEach((m) => {\n result.send(m)\n })\n bufferedMessages = []\n return (provider = result)\n }\n\n provider = input().then(onResolve, withMacroTask(onHalt))\n return provider\n }\n\n const disconnect = () => {\n if (!provider) return\n\n const finishIt = (input: JsonRpcConnection | null) => {\n subscriptionManager.onDisconnect()\n pendingResponses.clear()\n provider = null\n input?.disconnect()\n }\n\n if (provider instanceof Promise) {\n provider.then(finishIt, finishIt)\n provider = null\n } else finishIt(provider)\n }\n\n start()\n return {\n send,\n disconnect,\n }\n }\n\nconst withMacroTask =\n <Args extends Array<any>, T>(\n inputFn: (...args: Args) => Promise<T>,\n ): ((...args: Args) => Promise<T>) =>\n (...args) =>\n new Promise((res) => setTimeout(res, 0)).then(() => inputFn(...args))\n"],"names":["MessageType","input"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/json-rpc-message.ts","../src/get-proxy.ts","../src/get-sync-provider.ts"],"sourcesContent":["export const jsonRpcMsg = <T extends {}>(msg: T) =>\n JSON.stringify({\n jsonrpc: \"2.0\",\n ...msg,\n })\n","import { JsonRpcConnection } from \"@polkadot-api/json-rpc-provider\"\nimport { ReconnectableJsonRpcConnection } from \"./internal-types\"\nimport { jsonRpcMsg } from \"./json-rpc-message\"\n\nconst enum State {\n Connected,\n Connecting,\n Done,\n}\n\nconst enum OngoingMsgType {\n ChainHeadFollow,\n ChainHeadOperation,\n Other,\n}\ntype OngoingMsg =\n | {\n type: OngoingMsgType.ChainHeadFollow\n msg: string\n }\n | { type: OngoingMsgType.ChainHeadOperation; id: string }\n | { type: OngoingMsgType.Other; msg: string }\n\nconst unfollowMethods = new Set(\n [\"v1\", \"unstable\"].map((x) => `chainHead_${x}_unfollow`),\n)\n\nexport const getProxy: ReconnectableJsonRpcConnection = (\n toConsumer: (msg: string) => void,\n) => {\n let state:\n | {\n type: State.Connected\n connection: JsonRpcConnection\n onGoingRequests: Map<string, OngoingMsg>\n activeChainHeads: Set<string>\n }\n | { type: State.Connecting; pending: Array<string> }\n | { type: State.Done } = {\n type: State.Connecting,\n pending: [],\n }\n\n const onMsgFromProvider = (msg: string) => {\n if (state.type === State.Connected) {\n const parsed = JSON.parse(msg)\n if (\"id\" in parsed) {\n if (\n state.onGoingRequests.get(parsed.id)?.type ===\n OngoingMsgType.ChainHeadFollow\n )\n state.activeChainHeads.add(parsed.result)\n state.onGoingRequests.delete(parsed.id)\n } else {\n const { subscription, result } = parsed.params\n if (result?.event === \"stop\")\n state.activeChainHeads.delete(subscription)\n }\n }\n // If the state is \"Connecting\", then these are messages\n // sent from the `onHalt` function. So, we mus realy them\n if (state.type !== State.Done) toConsumer(msg)\n }\n\n const send = (msg: string) => {\n if (state.type === State.Done) return\n if (state.type === State.Connecting) {\n state.pending.push(msg)\n return\n }\n const parsed = JSON.parse(msg)\n if (unfollowMethods.has(parsed.method))\n state.activeChainHeads.delete(parsed.params[0])\n\n if (\"id\" in parsed) {\n const { method, id } = parsed as { method: string; id: string }\n const ongoingMsg: OngoingMsg = method.startsWith(\"chainHead\")\n ? method.endsWith(\"follow\")\n ? {\n type: OngoingMsgType.ChainHeadFollow,\n msg,\n }\n : { type: OngoingMsgType.ChainHeadOperation, id }\n : { type: OngoingMsgType.Other, msg }\n state.onGoingRequests.set(id, ongoingMsg)\n }\n\n state.connection.send(msg)\n }\n\n return {\n send,\n disconnect: () => {\n if (state.type === State.Done) return\n if (state.type === State.Connected) state.connection.disconnect()\n state = { type: State.Done }\n },\n connect: (cb) => {\n if (state.type !== State.Connecting) throw new Error(\"Nonesense\")\n\n const { pending } = state\n const onGoingRequests = new Map<string, OngoingMsg>()\n const activeChainHeads = new Set<string>()\n const onHalt = () => {\n state = {\n type: State.Connecting,\n pending: [],\n }\n activeChainHeads.forEach((subscription) => {\n // We don't send the messages directy to the consumer\n // b/c they could have disconnected after receiving one\n // of these messages. The `onMsgFromProvider` fn handles that\n onMsgFromProvider(\n jsonRpcMsg({\n params: {\n subscription,\n result: {\n event: \"stop\",\n internal: true,\n },\n },\n }),\n )\n })\n activeChainHeads.clear()\n for (const x of onGoingRequests.values()) {\n if (x.type === OngoingMsgType.ChainHeadOperation)\n onMsgFromProvider(\n jsonRpcMsg({\n id: x.id,\n error: { code: -32603, message: \"Internal error\" },\n internal: true,\n }),\n )\n else send(x.msg)\n }\n onGoingRequests.clear()\n }\n state = {\n type: State.Connected,\n connection: cb(onMsgFromProvider, onHalt),\n onGoingRequests,\n activeChainHeads,\n }\n pending.forEach(send)\n },\n }\n}\n","import type { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\nimport { getProxy } from \"./get-proxy\"\nimport { AsyncJsonRpcProvider } from \"./public-types\"\nimport { ConnectableJsonRpcConnection } from \"./internal-types\"\n\nexport const getSyncProvider =\n (input: () => Promise<AsyncJsonRpcProvider>): JsonRpcProvider =>\n (onMessage) => {\n let proxy: ConnectableJsonRpcConnection | null = getProxy(onMessage)\n\n const start = () => {\n input().then(\n (cb) => {\n if (!proxy) {\n try {\n cb(\n () => {},\n () => {},\n ).disconnect()\n } catch (_) {}\n } else\n proxy.connect((onMsg, onHalt) =>\n cb(onMsg, () => {\n onHalt()\n start()\n }),\n )\n },\n () => {\n proxy && setTimeout(start, 0)\n },\n )\n }\n\n start()\n return {\n send: (msg) => {\n proxy?.send(msg)\n },\n disconnect: () => {\n proxy?.disconnect()\n proxy = null\n },\n }\n }\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polkadot-api/json-rpc-provider-proxy",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"author": "Josep M Sobrepere (https://github.com/josepot)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dist"
|
|
36
36
|
],
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@polkadot-api/json-rpc-provider": "0.0.
|
|
38
|
+
"@polkadot-api/json-rpc-provider": "0.0.4"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build-core": "tsc --noEmit && rollup -c ../../../rollup.config.js",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
2
|
-
MessageType2[MessageType2["subscribe"] = 0] = "subscribe";
|
|
3
|
-
MessageType2[MessageType2["unsubscribe"] = 1] = "unsubscribe";
|
|
4
|
-
MessageType2[MessageType2["end"] = 2] = "end";
|
|
5
|
-
return MessageType2;
|
|
6
|
-
})(MessageType || {});
|
|
7
|
-
|
|
8
|
-
export { MessageType };
|
|
9
|
-
//# sourceMappingURL=internal-types.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"internal-types.mjs","sources":["../../src/internal-types.ts"],"sourcesContent":["export type RequestId = string | number | null\nexport type SubscriptionId = string | number\nexport type JsonMessage = {\n jsonrpc: \"2.0\"\n method: string\n params: {}\n}\n\nexport const enum MessageType {\n subscribe,\n unsubscribe,\n end,\n}\n\nexport interface SubscriptionLogic {\n onSent: (parsed: any) =>\n | {\n type: MessageType.subscribe\n id: RequestId\n onRes: (parsed: any) => { id: SubscriptionId } | null\n }\n | { type: MessageType.unsubscribe; id: SubscriptionId }\n | null\n onNotification: (\n parsed: any,\n ) => { type: MessageType.end; id: SubscriptionId } | null\n onAbort: (id: SubscriptionId) => void\n}\n"],"names":["MessageType"],"mappings":"AAQkB,IAAA,WAAA,qBAAAA,YAAX,KAAA;AACL,EAAAA,YAAA,CAAA,YAAA,CAAA,WAAA,CAAA,GAAA,CAAA,CAAA,GAAA,WAAA,CAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,aAAA,CAAA,GAAA,CAAA,CAAA,GAAA,aAAA,CAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,KAAA,CAAA,GAAA,CAAA,CAAA,GAAA,KAAA,CAAA;AAHgB,EAAAA,OAAAA,YAAAA,CAAAA;AAAA,CAAA,EAAA,WAAA,IAAA,EAAA;;;;"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { MessageType } from '../internal-types.mjs';
|
|
2
|
-
import { jsonRpcMsg } from '../json-rpc-message.mjs';
|
|
3
|
-
|
|
4
|
-
const [START_METHODS, STOP_METHODS, NOTIFICATION_METHODS] = [
|
|
5
|
-
"follow",
|
|
6
|
-
"unfollow",
|
|
7
|
-
"followEvent"
|
|
8
|
-
].map(
|
|
9
|
-
(name) => new Set(
|
|
10
|
-
["v1", "unstable"].map((version) => `chainHead_${version}_${name}`)
|
|
11
|
-
)
|
|
12
|
-
);
|
|
13
|
-
const STOP_EVENT = "stop";
|
|
14
|
-
const chainHeadFollow = (onMessage) => {
|
|
15
|
-
let notificationMethod = "";
|
|
16
|
-
return {
|
|
17
|
-
onSent(parsed) {
|
|
18
|
-
if (START_METHODS.has(parsed.method)) {
|
|
19
|
-
notificationMethod = parsed.method + "Event";
|
|
20
|
-
return {
|
|
21
|
-
type: MessageType.subscribe,
|
|
22
|
-
id: parsed.id,
|
|
23
|
-
onRes: (innerParsed) => innerParsed.id === parsed.id ? { id: innerParsed.result } : null
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
if (STOP_METHODS.has(parsed.method))
|
|
27
|
-
return {
|
|
28
|
-
type: MessageType.unsubscribe,
|
|
29
|
-
id: Object.values(parsed.params)[0]
|
|
30
|
-
};
|
|
31
|
-
return null;
|
|
32
|
-
},
|
|
33
|
-
onNotification(parsed) {
|
|
34
|
-
return NOTIFICATION_METHODS.has(parsed.method) && parsed.params.result.event === STOP_EVENT ? {
|
|
35
|
-
type: MessageType.end,
|
|
36
|
-
id: parsed.params.subscription
|
|
37
|
-
} : null;
|
|
38
|
-
},
|
|
39
|
-
onAbort: (id) => {
|
|
40
|
-
onMessage(
|
|
41
|
-
jsonRpcMsg({
|
|
42
|
-
method: notificationMethod,
|
|
43
|
-
params: {
|
|
44
|
-
subscription: id,
|
|
45
|
-
result: {
|
|
46
|
-
event: STOP_EVENT,
|
|
47
|
-
eventType: "internal"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export { chainHeadFollow };
|
|
57
|
-
//# sourceMappingURL=chainHeadFollow.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chainHeadFollow.mjs","sources":["../../../src/subscription-manager/chainHeadFollow.ts"],"sourcesContent":["import {\n MessageType,\n SubscriptionId,\n SubscriptionLogic,\n} from \"@/internal-types\"\nimport { jsonRpcMsg } from \"@/json-rpc-message\"\n\nconst [START_METHODS, STOP_METHODS, NOTIFICATION_METHODS] = [\n \"follow\",\n \"unfollow\",\n \"followEvent\",\n].map(\n (name) =>\n new Set(\n [\"v1\", \"unstable\"].map((version) => `chainHead_${version}_${name}`),\n ),\n)\nconst STOP_EVENT = \"stop\"\n\nexport const chainHeadFollow = (\n onMessage: (msg: string) => void,\n): SubscriptionLogic => {\n let notificationMethod = \"\"\n return {\n onSent(parsed) {\n if (START_METHODS.has(parsed.method)) {\n notificationMethod = parsed.method + \"Event\"\n return {\n type: MessageType.subscribe,\n id: parsed.id,\n onRes: (innerParsed) =>\n innerParsed.id === parsed.id ? { id: innerParsed.result } : null,\n }\n }\n\n if (STOP_METHODS.has(parsed.method))\n return {\n type: MessageType.unsubscribe,\n id: Object.values(parsed.params)[0] as string,\n }\n\n return null\n },\n onNotification(parsed) {\n return NOTIFICATION_METHODS.has(parsed.method) &&\n parsed.params.result.event === STOP_EVENT\n ? {\n type: MessageType.end,\n id: parsed.params.subscription as SubscriptionId,\n }\n : null\n },\n onAbort: (id) => {\n onMessage(\n jsonRpcMsg({\n method: notificationMethod,\n params: {\n subscription: id,\n result: {\n event: STOP_EVENT,\n eventType: \"internal\",\n },\n },\n }),\n )\n },\n }\n}\n"],"names":[],"mappings":";;;AAOA,MAAM,CAAC,aAAA,EAAe,YAAc,EAAA,oBAAoB,CAAI,GAAA;AAAA,EAC1D,QAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AACF,CAAE,CAAA,GAAA;AAAA,EACA,CAAC,SACC,IAAI,GAAA;AAAA,IACF,CAAC,IAAM,EAAA,UAAU,CAAE,CAAA,GAAA,CAAI,CAAC,OAAA,KAAY,CAAa,UAAA,EAAA,OAAO,CAAI,CAAA,EAAA,IAAI,CAAE,CAAA,CAAA;AAAA,GACpE;AACJ,CAAA,CAAA;AACA,MAAM,UAAa,GAAA,MAAA,CAAA;AAEN,MAAA,eAAA,GAAkB,CAC7B,SACsB,KAAA;AACtB,EAAA,IAAI,kBAAqB,GAAA,EAAA,CAAA;AACzB,EAAO,OAAA;AAAA,IACL,OAAO,MAAQ,EAAA;AACb,MAAA,IAAI,aAAc,CAAA,GAAA,CAAI,MAAO,CAAA,MAAM,CAAG,EAAA;AACpC,QAAA,kBAAA,GAAqB,OAAO,MAAS,GAAA,OAAA,CAAA;AACrC,QAAO,OAAA;AAAA,UACL,MAAM,WAAY,CAAA,SAAA;AAAA,UAClB,IAAI,MAAO,CAAA,EAAA;AAAA,UACX,KAAA,EAAO,CAAC,WAAA,KACN,WAAY,CAAA,EAAA,KAAO,MAAO,CAAA,EAAA,GAAK,EAAE,EAAA,EAAI,WAAY,CAAA,MAAA,EAAW,GAAA,IAAA;AAAA,SAChE,CAAA;AAAA,OACF;AAEA,MAAI,IAAA,YAAA,CAAa,GAAI,CAAA,MAAA,CAAO,MAAM,CAAA;AAChC,QAAO,OAAA;AAAA,UACL,MAAM,WAAY,CAAA,WAAA;AAAA,UAClB,IAAI,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,MAAM,EAAE,CAAC,CAAA;AAAA,SACpC,CAAA;AAEF,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAAA,IACA,eAAe,MAAQ,EAAA;AACrB,MAAO,OAAA,oBAAA,CAAqB,IAAI,MAAO,CAAA,MAAM,KAC3C,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,KAAA,KAAU,UAC7B,GAAA;AAAA,QACE,MAAM,WAAY,CAAA,GAAA;AAAA,QAClB,EAAA,EAAI,OAAO,MAAO,CAAA,YAAA;AAAA,OAEpB,GAAA,IAAA,CAAA;AAAA,KACN;AAAA,IACA,OAAA,EAAS,CAAC,EAAO,KAAA;AACf,MAAA,SAAA;AAAA,QACE,UAAW,CAAA;AAAA,UACT,MAAQ,EAAA,kBAAA;AAAA,UACR,MAAQ,EAAA;AAAA,YACN,YAAc,EAAA,EAAA;AAAA,YACd,MAAQ,EAAA;AAAA,cACN,KAAO,EAAA,UAAA;AAAA,cACP,SAAW,EAAA,UAAA;AAAA,aACb;AAAA,WACF;AAAA,SACD,CAAA;AAAA,OACH,CAAA;AAAA,KACF;AAAA,GACF,CAAA;AACF;;;;"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { MessageType } from '../internal-types.mjs';
|
|
2
|
-
import { chainHeadFollow } from './chainHeadFollow.mjs';
|
|
3
|
-
|
|
4
|
-
const addSubscription = ({
|
|
5
|
-
onSent,
|
|
6
|
-
onNotification,
|
|
7
|
-
onAbort
|
|
8
|
-
}) => {
|
|
9
|
-
const preActive = /* @__PURE__ */ new Map();
|
|
10
|
-
const active = /* @__PURE__ */ new Set();
|
|
11
|
-
const onDisconnect = () => {
|
|
12
|
-
preActive.clear();
|
|
13
|
-
active.clear();
|
|
14
|
-
};
|
|
15
|
-
return {
|
|
16
|
-
onSent(parsed) {
|
|
17
|
-
const result = onSent(parsed);
|
|
18
|
-
if (result) {
|
|
19
|
-
if (result.type === MessageType.subscribe)
|
|
20
|
-
preActive.set(result.id, result.onRes);
|
|
21
|
-
else active.delete(result.id);
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
onResponse(parsed) {
|
|
25
|
-
const match = preActive.get(parsed.id)?.(parsed);
|
|
26
|
-
if (match) {
|
|
27
|
-
preActive.delete(parsed.id);
|
|
28
|
-
active.add(match.id);
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
onNotifiaction(parsed) {
|
|
32
|
-
const result = onNotification(parsed);
|
|
33
|
-
if (result) active.delete(result.id);
|
|
34
|
-
},
|
|
35
|
-
onDisconnect,
|
|
36
|
-
onAbort() {
|
|
37
|
-
const activeCopy = [...active];
|
|
38
|
-
onDisconnect();
|
|
39
|
-
activeCopy.forEach(onAbort);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
const getSubscriptionManager = (onMessage) => addSubscription(chainHeadFollow(onMessage));
|
|
44
|
-
|
|
45
|
-
export { addSubscription, getSubscriptionManager };
|
|
46
|
-
//# sourceMappingURL=subscription-manager.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"subscription-manager.mjs","sources":["../../../src/subscription-manager/subscription-manager.ts"],"sourcesContent":["import {\n MessageType,\n type RequestId,\n type SubscriptionId,\n type SubscriptionLogic,\n} from \"../internal-types\"\nimport { chainHeadFollow } from \"./chainHeadFollow\"\n\nexport const addSubscription = ({\n onSent,\n onNotification,\n onAbort,\n}: SubscriptionLogic) => {\n const preActive = new Map<\n RequestId,\n (parsed: any) => { id: SubscriptionId } | null\n >()\n const active = new Set<SubscriptionId>()\n\n const onDisconnect = () => {\n preActive.clear()\n active.clear()\n }\n\n return {\n onSent(parsed: any) {\n const result = onSent(parsed)\n if (result) {\n if (result.type === MessageType.subscribe)\n preActive.set(result.id, result.onRes)\n else active.delete(result.id)\n }\n },\n onResponse(parsed: any) {\n const match = preActive.get(parsed.id)?.(parsed)\n if (match) {\n preActive.delete(parsed.id)\n active.add(match.id)\n }\n },\n onNotifiaction(parsed: any) {\n const result = onNotification(parsed)\n if (result) active.delete(result.id)\n },\n onDisconnect,\n onAbort() {\n const activeCopy = [...active]\n onDisconnect()\n activeCopy.forEach(onAbort)\n },\n }\n}\n\nexport const getSubscriptionManager = (onMessage: (msg: string) => void) =>\n addSubscription(chainHeadFollow(onMessage))\n"],"names":[],"mappings":";;;AAQO,MAAM,kBAAkB,CAAC;AAAA,EAC9B,MAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AACF,CAAyB,KAAA;AACvB,EAAM,MAAA,SAAA,uBAAgB,GAGpB,EAAA,CAAA;AACF,EAAM,MAAA,MAAA,uBAAa,GAAoB,EAAA,CAAA;AAEvC,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,SAAA,CAAU,KAAM,EAAA,CAAA;AAChB,IAAA,MAAA,CAAO,KAAM,EAAA,CAAA;AAAA,GACf,CAAA;AAEA,EAAO,OAAA;AAAA,IACL,OAAO,MAAa,EAAA;AAClB,MAAM,MAAA,MAAA,GAAS,OAAO,MAAM,CAAA,CAAA;AAC5B,MAAA,IAAI,MAAQ,EAAA;AACV,QAAI,IAAA,MAAA,CAAO,SAAS,WAAY,CAAA,SAAA;AAC9B,UAAA,SAAA,CAAU,GAAI,CAAA,MAAA,CAAO,EAAI,EAAA,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,aAClC,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAAA,OAC9B;AAAA,KACF;AAAA,IACA,WAAW,MAAa,EAAA;AACtB,MAAA,MAAM,QAAQ,SAAU,CAAA,GAAA,CAAI,MAAO,CAAA,EAAE,IAAI,MAAM,CAAA,CAAA;AAC/C,MAAA,IAAI,KAAO,EAAA;AACT,QAAU,SAAA,CAAA,MAAA,CAAO,OAAO,EAAE,CAAA,CAAA;AAC1B,QAAO,MAAA,CAAA,GAAA,CAAI,MAAM,EAAE,CAAA,CAAA;AAAA,OACrB;AAAA,KACF;AAAA,IACA,eAAe,MAAa,EAAA;AAC1B,MAAM,MAAA,MAAA,GAAS,eAAe,MAAM,CAAA,CAAA;AACpC,MAAA,IAAI,MAAQ,EAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAAA,KACrC;AAAA,IACA,YAAA;AAAA,IACA,OAAU,GAAA;AACR,MAAM,MAAA,UAAA,GAAa,CAAC,GAAG,MAAM,CAAA,CAAA;AAC7B,MAAa,YAAA,EAAA,CAAA;AACb,MAAA,UAAA,CAAW,QAAQ,OAAO,CAAA,CAAA;AAAA,KAC5B;AAAA,GACF,CAAA;AACF,EAAA;AAEO,MAAM,yBAAyB,CAAC,SAAA,KACrC,eAAgB,CAAA,eAAA,CAAgB,SAAS,CAAC;;;;"}
|